コード例 #1
0
        public void Resample_8To8()  //broken only on Linux?
        {
            //-- 1. Create a raw sine sample which shall be 44100 Hz and 16 Bit
            int sampleLength = 500;

            byte[] buffer = new byte[sampleLength];
            for (int i = 0; i < sampleLength; i++)
            {
                buffer [i] = (byte)(128 + 120.0f * Math.Sin(((float)i / (float)sampleLength) * (Math.PI * 2.0f)));
            }

            using (BinaryWriter writerRaw = new BinaryWriter(File.Open("test2_in_sine_44100_8.raw", FileMode.Create))) {
                for (uint i = 0; i < sampleLength; i++)
                {
                    writerRaw.Write(buffer [i]);
                }
            }

            GCHandle _hGCFile;

            // now create a pinned handle, so that the Garbage Collector will not move this object
            _hGCFile = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            int handle = Bass.BASS_StreamCreate(44100, 1, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_8BITS, BASSStreamProc.STREAMPROC_PUSH);

            int ret = Bass.BASS_StreamPutData(handle, _hGCFile.AddrOfPinnedObject(), buffer.Length * sizeof(byte) | (int)BASSStreamProc.BASS_STREAMPROC_END);

            Assert.AreEqual(buffer.Length * sizeof(byte), ret);


            //-- 2. Mix it
            int mixer = BassMix.BASS_Mixer_StreamCreate(11025, 1, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_8BITS);

            // add channel to mixer
            bool isMixerGood = BassMix.BASS_Mixer_StreamAddChannel(mixer, handle, BASSFlag.BASS_MIXER_NORAMPIN);

            Assert.AreEqual(true, isMixerGood);

            //-- 3. grab Stream and compare
            byte[] buffer2 = new byte[1000];

            // total data written to the new byte[] buffer
            int totalDataWritten = Bass.BASS_ChannelGetData(mixer, buffer2, (int)1000);

            Console.WriteLine("totalDataWritten " + totalDataWritten);

            using (BinaryWriter writerRaw = new BinaryWriter(File.Open("test2_out_sine_11025_8.raw", FileMode.Create))) {
                for (uint i = 0; i < totalDataWritten; i++)
                {
                    writerRaw.Write(buffer2 [i]);
                }
            }

            string hashGen = MD5Utils.GenerateMd5Hash(buffer2);

            Bass.BASS_StreamFree(handle);
            Bass.BASS_StreamFree(mixer);

            Assert.AreEqual("50bce9c536e98667534747f0a5f06ebd", hashGen);
        }
コード例 #2
0
ファイル: SimpleMix.cs プロジェクト: MackZ28/EZiePlayer
        private void Simple_Load(object sender, System.EventArgs e)
        {
            // BassNet.Registration("your email", "your regkey");

            if (!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle))
            {
                MessageBox.Show(this, "Bass_Init error!");
                this.Close();
                return;
            }
            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, 200);
            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 20);

            // already create a mixer
            _mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT);
            if (_mixer == 0)
            {
                MessageBox.Show(this, "Could not create mixer!");
                Bass.BASS_Free();
                this.Close();
                return;
            }

            _mixerStallSync = new SYNCPROC(OnMixerStall);
            Bass.BASS_ChannelSetSync(_mixer, BASSSync.BASS_SYNC_STALL, 0L, _mixerStallSync, IntPtr.Zero);

            timerUpdate.Start();
            Bass.BASS_ChannelPlay(_mixer, false);
        }
コード例 #3
0
ファイル: DelayTool.cs プロジェクト: Ashoat/delay
        public void start(double delay)
        {
            latency = (float)delay / 10;
            var str   = (inlist.Items[inlist.SelectedIndex] as string);
            var array = str.Split(' ');

            sourceIndex = Convert.ToInt32(array[0]);
            str         = (outlist.Items[outlist.SelectedIndex] as string);
            array       = str.Split(' ');
            outIndex    = Convert.ToInt32(array[0]);
            Console.WriteLine(sourceIndex + " " + outIndex);
            Console.WriteLine(delay);

            stop();
            Bass.BASS_Init(0, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); // "No Sound" device init

            // Garbage collector can't track the reference BassWasapi holds,
            // so we're adding a reference here to prevent garbage collection
            inProc  = sourceWasapiProc;
            outProc = outWasapiProc;
            BassWasapi.BASS_WASAPI_Init(sourceIndex, 44100, 0, 0, 1, 0, inProc, IntPtr.Zero);
            BassWasapi.BASS_WASAPI_Init(outIndex, 44100, 0, 0, 4 * latency, 1 * latency, outProc, IntPtr.Zero);

            BassWasapi.BASS_WASAPI_SetDevice(outIndex);
            pushstr = Bass.BASS_StreamCreatePush(44100, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT, IntPtr.Zero);
            outstr  = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
            BassMix.BASS_Mixer_StreamAddChannel(outstr, pushstr, 0);

            BassWasapi.BASS_WASAPI_SetDevice(sourceIndex);
            BassWasapi.BASS_WASAPI_Start();
            BassWasapi.BASS_WASAPI_SetDevice(outIndex);
            BassWasapi.BASS_WASAPI_Start();
        }
コード例 #4
0
        /// <summary>
        ///   Recode the file
        /// </summary>
        /// <param name = "fileName">Initial file</param>
        /// <param name = "outFileName">Target file</param>
        /// <param name = "targetSampleRate">Target sample rate</param>
        public void RecodeTheFile(string fileName, string outFileName, int targetSampleRate)
        {
            int      stream = Un4seen.Bass.Bass.BASS_StreamCreateFile(fileName, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_MONO | BASSFlag.BASS_SAMPLE_FLOAT);
            TAG_INFO tags   = new TAG_INFO();

            BassTags.BASS_TAG_GetFromFile(stream, tags);
            int mixerStream = BassMix.BASS_Mixer_StreamCreate(targetSampleRate, 1, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_MONO | BASSFlag.BASS_SAMPLE_FLOAT);

            if (BassMix.BASS_Mixer_StreamAddChannel(mixerStream, stream, BASSFlag.BASS_MIXER_FILTER))
            {
                WaveWriter waveWriter = new WaveWriter(outFileName, mixerStream, true);
                const int  length     = 5512 * 10 * 4;
                float[]    buffer     = new float[length];
                while (true)
                {
                    int bytesRead = Un4seen.Bass.Bass.BASS_ChannelGetData(mixerStream, buffer, length);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    waveWriter.Write(buffer, bytesRead);
                }
                waveWriter.Close();
            }
            else
            {
                throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString());
            }
        }
コード例 #5
0
        /// <summary>
        ///     Initializes a decoder mixer channel.
        /// </summary>
        /// <returns>The channel Id of the mixer channel</returns>
        public static int InitializeMixerChannel()
        {
            var mixerChannel = BassMix.BASS_Mixer_StreamCreate(DefaultSampleRate, 2,
                                                               BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE);

            if (mixerChannel == 0)
            {
                throw new Exception("Cannot create Bass Mixer.");
            }
            return(mixerChannel);
        }
コード例 #6
0
        public int CreateBassMixer(BMSSong pSong)
        {
            int mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_END);
            Dictionary <AudioSample, int> samples = PreloadSamples(pSong.AudioSamples);
            List <Track> tracks = pSong.Tracks;

            for (int i = 0; i < tracks.Count; i++)
            {
                MixTrack(mixer, tracks[i], samples);
            }

            return(mixer);
        }
コード例 #7
0
        public void CreateMixerChannel()
        {
            int mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MIXER_END);

            this.StreamMixer = mixer;

            if (ChannelType != CHANNEL_TYPE.REMOTE_URL)
            {
                syncProcEnd = new SYNCPROC(SyncProcEndCallback);

                mySyncHandleEnd = Bass.BASS_ChannelSetSync(mixer, BASSSync.BASS_SYNC_END, 0, syncProcEnd, IntPtr.Zero);
            }
        }
コード例 #8
0
        /// <summary>
        /// Creates the visualization Bass stream.
        /// </summary>
        private void CreateVizStream()
        {
            BASSFlag streamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT;

            int handle = Bass.BASS_StreamCreate(
                _inputStream.SampleRate,
                _inputStream.Channels,
                streamFlags,
                _vizRawStreamWriteProcDelegate,
                IntPtr.Zero);

            if (handle == BassConstants.BassInvalidHandle)
            {
                throw new BassLibraryException("BASS_StreamCreate");
            }

            _vizRawStream = BassStream.Create(handle);

            // Todo: apply AGC

            streamFlags = BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE;

            handle = BassMix.BASS_Mixer_StreamCreate(_inputStream.SampleRate, 2, streamFlags);
            if (handle == BassConstants.BassInvalidHandle)
            {
                throw new BassLibraryException("BASS_StreamCreate");
            }

            _vizStream = BassStream.Create(handle);

            streamFlags = BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_MIXER_MATRIX;

            if (!BassMix.BASS_Mixer_StreamAddChannel(_vizStream.Handle, _vizRawStream.Handle, streamFlags))
            {
                throw new BassLibraryException("BASS_Mixer_StreamAddChannel");
            }

            // TODO Albert 2010-02-27: What is this?
            if (_inputStream.Channels == 1)
            {
                float[,] mixMatrix = new float[2, 1];
                mixMatrix[0, 0]    = 1;
                mixMatrix[1, 0]    = 1;

                if (!BassMix.BASS_Mixer_ChannelSetMatrix(_vizRawStream.Handle, mixMatrix))
                {
                    throw new BassLibraryException("BASS_Mixer_ChannelSetMatrix");
                }
            }
        }
コード例 #9
0
ファイル: Scene.cs プロジェクト: tsfstarr/softrope-desktop
        public Scene()
        {
            FadeOutLength             = DEFAULT_FADEOUT_LENGTH;
            Name                      = "Unnamed Scene";
            slideSync                 = new SYNCPROC(SlideSync);
            SoundEffects.ListChanged += new ListChangedEventHandler(SoundEffects_ListChanged);
            SceneMixerChannel         = BassMix.BASS_Mixer_StreamCreate(44100, 2,
                                                                        BASSFlag.BASS_MIXER_NONSTOP |
                                                                        BASSFlag.BASS_STREAM_DECODE |
                                                                        BASSFlag.BASS_SAMPLE_FLOAT);
            BassMix.BASS_Mixer_ChannelFlags(SceneMixerChannel, BASSFlag.BASS_MIXER_NORAMPIN, BASSFlag.BASS_MIXER_NORAMPIN);
            Bass.BASS_ChannelSetSync(SceneMixerChannel, BASSSync.BASS_SYNC_SLIDE, 0, slideSync, IntPtr.Zero);

            this.SceneVolume = 1;
            this.IsFading    = false;
        }
コード例 #10
0
        public static int PlugChannelToMixer(int handle, int freq, int chans, int res)
        {
            BASSFlag bassFlag = BASSFlag.BASS_STREAM_DECODE;

            if (res == 8)
            {
                bassFlag |= BASSFlag.BASS_SAMPLE_8BITS;
            }

            // this will be the final mixer output stream being played
            int mixer = BassMix.BASS_Mixer_StreamCreate(freq, chans, bassFlag);

            // add channel to mixer
            bool isMixerGood = BassMix.BASS_Mixer_StreamAddChannel(mixer, handle, BASSFlag.BASS_MIXER_NORAMPIN);

            return(mixer);
        }
コード例 #11
0
 public SoundEffect()
 {
     IsLooping            = false;
     LoopGap              = 0;
     LoopGapVariance      = 0;
     gapTimer.Interval    = 1;
     SoundEffectVolume    = 1;
     gapTimer.Elapsed    += new System.Timers.ElapsedEventHandler(gapTimer_Elapsed);
     Samples.ListChanged += new ListChangedEventHandler(Samples_ListChanged);
     endSync              = new SYNCPROC(EndSync);
     Name = "Unnamed Sound Effect";
     SoundEffectMixerChannel = BassMix.BASS_Mixer_StreamCreate(44100, 2,
                                                               BASSFlag.BASS_MIXER_NONSTOP |
                                                               BASSFlag.BASS_STREAM_DECODE |
                                                               BASSFlag.BASS_SAMPLE_FLOAT);
     BassMix.BASS_Mixer_ChannelFlags(SoundEffectMixerChannel, BASSFlag.BASS_MIXER_NORAMPIN, BASSFlag.BASS_MIXER_NORAMPIN);
 }
コード例 #12
0
        public static int MixerStreamCreate(int samplerate)
        {
            BASSFlag mixerFlags = BASSFlag.BASS_SAMPLE_FLOAT;

            if (Player.IsAsioInitialized || Player.IsWasapiInitialized)
            {
                mixerFlags |= BASSFlag.BASS_STREAM_DECODE;
            }

            m_mixerChannel = BassMix.BASS_Mixer_StreamCreate(samplerate, 2, mixerFlags);

            Console.WriteLine("Player.IsBassInitialized " + Player.IsBassInitialized);
            Console.WriteLine("Player.IsAsioInitialized " + Player.IsAsioInitialized);
            Console.WriteLine("Player.IsWasapiInitialized " + Player.IsWasapiInitialized);

            return(m_mixerChannel);
        }
コード例 #13
0
        /// <summary>
        /// Called when a stream has been created. This actually starts the playback of the stream.
        /// </summary>
        /// <param name="track">The track that is to be played.</param>
        /// <param name="stream">The BASS.NET stream pointer to play.</param>
        protected virtual void StreamCreated(IAudioItem track, int stream)
        {
            // Init mixer
            if (_mixer == -1)
            {
                _mixer = BassMix.BASS_Mixer_StreamCreate(44100, 6, BASSFlag.BASS_MIXER_END);

                // Set playback done callback on mixer
                _channelEndCallback = new SYNCPROC(ChannelEnd);
                Bass.BASS_ChannelSetSync(_mixer, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, _channelEndCallback, IntPtr.Zero);
            }

            // Load streamin mixer
            bool ok = BassMix.BASS_Mixer_StreamAddChannel(_mixer, stream, BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_MIXER_MATRIX);

            if (!ok)
            {
                Log(Bass.BASS_ErrorGetCode().ToString(), Logger.LogLevel.Error);
            }

            // Set matrix
            SetMatrix(stream);

            // Remove current channel from mixer
            if (_currentStream != -1)
            {
                BassMix.BASS_Mixer_ChannelRemove(_currentStream);
                Bass.BASS_StreamFree(_currentStream);
            }

            //
            if (track is IWebcast)
            {
                SYNCPROC _mySync = new SYNCPROC(MetaSync);
                Bass.BASS_ChannelSetSync(_currentStream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero);
            }

            // Play it!
            Bass.BASS_ChannelSetPosition(_mixer, 0);
            Bass.BASS_Start();
            Bass.BASS_ChannelPlay(_mixer, false);

            // Set current stuff
            _currentStream = stream;
        }
コード例 #14
0
 public BassWasapiHandler(int device, bool exclusive, bool eventSystem, int freq, int chans, float buffer, float period)
 {
     this._device      = device;
     this._exclusive   = exclusive;
     this._eventSystem = eventSystem;
     if (!BassWasapi.BASS_WASAPI_GetDeviceInfo(device, this._wasapiDeviceInfo))
     {
         throw new ArgumentException("Invalid device: " + Enum.GetName(typeof(BASSError), Bass.Bass.BASS_ErrorGetCode()));
     }
     if (exclusive)
     {
         this._numchans = chans;
     }
     else
     {
         this._numchans = this._wasapiDeviceInfo.mixchans;
     }
     if (exclusive)
     {
         this._samplerate = freq;
     }
     else
     {
         this._samplerate = this._wasapiDeviceInfo.mixfreq;
     }
     this._updatePeriod = period;
     if (buffer == 0f)
     {
         this._bufferLength = ((this._updatePeriod == 0f) ? this._wasapiDeviceInfo.defperiod : this._updatePeriod) * 4f;
     }
     else
     {
         this._bufferLength = buffer;
     }
     if (this.IsInput)
     {
         this.UseInput = true;
         return;
     }
     this._internalMixer = BassMix.BASS_Mixer_StreamCreate(this._samplerate, this._numchans, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_AAC_FRAME960);
     if (this._internalMixer == 0)
     {
         throw new NotSupportedException("Internal Mixer: " + Enum.GetName(typeof(BASSError), Bass.Bass.BASS_ErrorGetCode()));
     }
 }
コード例 #15
0
        /// <summary>
        ///     Initializes the mixer channel.
        /// </summary>
        /// <returns>The channel Id of the mixer channel</returns>
        public static int InitializeOutputChannel(int deviceId)
        {
            var currentDeviceId = AudioEngineHelper.GetCurrentDeviceId();

            AudioEngineHelper.SetDevice(deviceId);

            var mixerChannel = BassMix.BASS_Mixer_StreamCreate(DefaultSampleRate, 2, BASSFlag.BASS_SAMPLE_FLOAT);

            if (mixerChannel == 0)
            {
                throw new Exception("Cannot create Bass Mixer.");
            }

            AssignChannelToDevice(mixerChannel, deviceId);
            AudioEngineHelper.SetDevice(currentDeviceId);

            return(mixerChannel);
        }
コード例 #16
0
ファイル: Module.cs プロジェクト: tsfstarr/softrope-desktop
        public Module()
        {
            Scenes              = new BindingList <Scene>();
            IsDirty             = true;
            Scenes.ListChanged += new ListChangedEventHandler(Scenes_ListChanged);
            ModuleMixerChannel  = BassMix.BASS_Mixer_StreamCreate(44100, 2,
                                                                  BASSFlag.BASS_MIXER_NONSTOP |
                                                                  BASSFlag.BASS_SAMPLE_FLOAT);
            BassMix.BASS_Mixer_ChannelFlags(ModuleMixerChannel, BASSFlag.BASS_MIXER_NORAMPIN, BASSFlag.BASS_MIXER_NORAMPIN);

            Bass.BASS_ChannelPlay(ModuleMixerChannel, false);

            reverbChannel      = Bass.BASS_ChannelSetFX(ModuleMixerChannel, BASSFXType.BASS_FX_DX8_REVERB, 1000);
            reverb             = new BASS_DX8_REVERB();
            reverb.fReverbMix  = -96;
            reverb.fReverbTime = 0;
            Bass.BASS_FXSetParameters(reverbChannel, reverb);
        }
コード例 #17
0
ファイル: BassDecoder.cs プロジェクト: ninjawerk/Safire2
        public override void Load(string file)
        {
            // Dispose on every new load
            Dispose(false);

            ready = false;

            // Create a stream channel from a file (use BASS_STREAM_PRESCAN for mp3?)
            bassStream = Bass.BASS_StreamCreateFile(file, 0L, 0L, BASSFlag.BASS_STREAM_DECODE);
            if (bassStream != 0)
            {
                var info = Bass.BASS_ChannelGetInfo(bassStream);

                this.sourceBitDepth   = info.Is8bit ? 8 : (info.Is32bit ? 32 : 16);
                this.sourceSampleRate = info.freq;
                this.sourceChannels   = info.chans;

                this.sampleRate = info.freq;
                this.channels   = info.chans;

                duration = (int)Bass.BASS_ChannelBytes2Seconds(bassStream, Bass.BASS_ChannelGetLength(bassStream));

                if (this.resample)
                {
                    this.sampleRate = 11025;
                    this.channels   = 1;

                    // Create resample stream.
                    bassMixer = BassMix.BASS_Mixer_StreamCreate(this.sampleRate, this.channels,
                                                                BASSFlag.BASS_MIXER_END | BASSFlag.BASS_STREAM_DECODE);

                    if (bassMixer == 0)
                    {
                        return;
                    }

                    BassMix.BASS_Mixer_StreamAddChannel(bassMixer, bassStream, 0);
                }

                ready = (!info.Is8bit && !info.Is32bit);
            }
        }
コード例 #18
0
ファイル: Encoder.cs プロジェクト: MackZ28/EZiePlayer
        private void buttonPlaySource_Click(object sender, System.EventArgs e)
        {
            Bass.BASS_StreamFree(_streamA);
            Bass.BASS_StreamFree(_streamB);
            Bass.BASS_StreamFree(_mixerStream);
            // mixer setup
            // now we need some channels to plug them in...create two decoding sources
            _streamA = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
            _streamB = Bass.BASS_StreamCreateFile(_fileNameOutput, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
            BASS_CHANNELINFO i = new BASS_CHANNELINFO();

            Bass.BASS_ChannelGetInfo(_streamA, i);
            // this will be the final mixer output stream being played
            _mixerStream = BassMix.BASS_Mixer_StreamCreate(i.freq, 4, BASSFlag.BASS_DEFAULT);
            // finally we plug them into the mixer (and upmix it to 4 channels - we assume the source to be stereo)
            bool okA = BassMix.BASS_Mixer_StreamAddChannel(_mixerStream, _streamA, BASSFlag.BASS_MIXER_MATRIX | BASSFlag.BASS_STREAM_AUTOFREE);
            bool okB = BassMix.BASS_Mixer_StreamAddChannel(_mixerStream, _streamB, BASSFlag.BASS_STREAM_AUTOFREE);

            // a matrix for A!
            float[,] matrixA = new float[4, 2] {            // stereo to quad matrix
                { 1, 0 },                                   // left front out = left in
                { 0, 1 },                                   // right front out = right in
                { 1, 0 },                                   // left rear out = left in
                { 0, 1 }                                    // right rear out = right in
            };
            // apply the matrix to stream A only
            BassMix.BASS_Mixer_ChannelSetMatrix(_streamA, matrixA);
            // just so show how to get it back...
            float[,] matrixGet = new float[4, 2];
            BassMix.BASS_Mixer_ChannelGetMatrix(_streamA, matrixGet);
            // mute streamB at the beginning
            this.trackBarCrossFader.Value = -100;
            Bass.BASS_ChannelSetAttribute(_streamB, BASSAttribute.BASS_ATTRIB_VOL, 0f);

            // and play it...
            if (Bass.BASS_ChannelPlay(_mixerStream, false))
            {
                this.label1.Text = "Playing! Use the crossfader...";
            }
        }
コード例 #19
0
        /// <summary>
        /// Create a mixer to be used as Output stream.
        /// We currently need this in case of Up- or Downmixing
        /// </summary>
        private void CreateMixer(int channels)
        {
            _mixerHandle = BassMix.BASS_Mixer_StreamCreate(_inputStream.SampleRate, channels, MIXER_FLAGS);
            if (_mixerHandle == BassConstants.BassInvalidHandle)
            {
                throw new BassLibraryException("BASS_Mixer_StreamCreate");
            }

            _mixerStream = BassStream.Create(_mixerHandle);

            // Now Attach the Input Stream to the mixer
            try
            {
                Bass.BASS_ChannelLock(_mixerHandle, true);

                bool result = BassMix.BASS_Mixer_StreamAddChannel(_mixerHandle, _inputStream.Handle,
                                                                  BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_BUFFER |
                                                                  BASSFlag.BASS_MIXER_MATRIX | BASSFlag.BASS_MIXER_DOWNMIX |
                                                                  BASSFlag.BASS_STREAM_AUTOFREE
                                                                  );
                if (!result)
                {
                    throw new BassLibraryException("BASS_UpDownMix_StreamAddChannel");
                }
            }
            finally
            {
                Bass.BASS_ChannelLock(_mixerHandle, false);
            }

            if (_mixingMatrix != null)
            {
                bool result = BassMix.BASS_Mixer_ChannelSetMatrix(_inputStream.Handle, _mixingMatrix);
                if (!result)
                {
                    throw new BassLibraryException("BASS_UpDownMix_SetMixingMatrix");
                }
            }
        }
コード例 #20
0
ファイル: AudioPlayer.cs プロジェクト: rich98521/ABPlayer
        public static void Play(string file, bool loadOnly)
        {
            Stop();
            baseStreamHandle = Bass.BASS_StreamCreateFile(file, 0, 0, BASSFlag.BASS_STREAM_DECODE);
            BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(baseStreamHandle);

            mixStreamHandle = BassMix.BASS_Mixer_StreamCreate(info.freq, info.chans, BASSFlag.BASS_STREAM_DECODE);
            BassMix.BASS_Mixer_StreamAddChannel(mixStreamHandle, baseStreamHandle, BASSFlag.BASS_MIXER_MATRIX);
            streamHandle = BassFx.BASS_FX_TempoCreate(mixStreamHandle, BASSFlag.BASS_FX_FREESOURCE);
            Mono         = mono;
            Speed        = speed;
            if (!loadOnly)
            {
                Bass.BASS_ChannelPlay(streamHandle, false);
            }
            BASSError er = Bass.BASS_ErrorGetCode();

            syncProc = new SYNCPROC(AudioEnded);
            Bass.BASS_ChannelSetSync(streamHandle, BASSSync.BASS_SYNC_END, 0, syncProc, IntPtr.Zero);
            Playing    = !loadOnly;
            FileLoaded = true;
        }
コード例 #21
0
        public void Play_With_Buildup()
        {
            Stop();
            if (InitBass(HZ))
            {
                Channel = BassMix.BASS_Mixer_StreamCreate(HZ, 2, BASSFlag.BASS_MIXER_END);

                point_B = GCHandle.Alloc(build_mem, GCHandleType.Pinned);
                point_L = GCHandle.Alloc(loop_mem, GCHandleType.Pinned);

                Stream_B  = Bass.BASS_StreamCreateFile(point_B.AddrOfPinnedObject(), 0, build_mem.LongLength, BASSFlag.BASS_STREAM_DECODE);
                build_len = Bass.BASS_ChannelGetLength(Stream_B, BASSMode.BASS_POS_BYTES);

                Stream_L = Bass.BASS_StreamCreateFile(point_L.AddrOfPinnedObject(), 0, loop_mem.LongLength, BASSFlag.BASS_STREAM_DECODE);
                loop_len = Bass.BASS_ChannelGetLength(Stream_L);

                BassMix.BASS_Mixer_StreamAddChannel(Channel, Stream_B, BASSFlag.BASS_DEFAULT);
                BassMix.BASS_Mixer_StreamAddChannelEx(Channel, Stream_L, BASSFlag.BASS_MIXER_NORAMPIN, build_len, 0);

                _loopSync = BassMix.BASS_Mixer_ChannelSetSync(Stream_L, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, loop_len, _loopSyncCallback, new IntPtr(1));
            }
        }
コード例 #22
0
ファイル: MixerChannelInfo.cs プロジェクト: vnmone/vvvv-sdk
        public override void Initialize(int deviceid)
        {
            Bass.BASS_SetDevice(deviceid);

            BASSFlag flag = BASSFlag.BASS_DEFAULT | BASSFlag.BASS_SAMPLE_FLOAT;

            if (this.IsDecoding)
            {
                flag = flag | BASSFlag.BASS_STREAM_DECODE;
            }

            int handle = BassMix.BASS_Mixer_StreamCreate(44100, this.NumChans, flag);

            this.BassHandle = handle;

            //Add the channel list in bass now
            foreach (ChannelInfo info in this.Streams)
            {
                if (!info.BassHandle.HasValue)
                {
                    info.Initialize(deviceid);
                }
                else
                {
                    if (info.BassHandle.Value == 0)
                    {
                        info.Initialize(deviceid);
                    }
                }
                BassMix.BASS_Mixer_StreamAddChannel(this.BassHandle.Value, info.BassHandle.Value, BASSFlag.BASS_MIXER_MATRIX | BASSFlag.BASS_MIXER_BUFFER);
                info.Play = info.Play;
            }

            this.Play = this.Play;

            //Bass.BASS_ChannelPlay(this.BassHandle.Value, false);
            this.OnInitialize();
        }
コード例 #23
0
        public void startDSP()
        {
            // Try to start the DSP
            // possible errors may include faulty audio drives/hardware, or restricted hardware access
            // or maybe the library just isn't there, or isn't working
            try
            {
                _isItLoaded = Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
            }
            catch (Exception E)
            {
                Console.WriteLine(E.ToString());
            }

            if (running())
            {
                // the basic functionality here for construction of the mixer
                // try to use floating point sampling (if hardware can even do it)
                _mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT);
                _vis   = new Visuals();

                Bass.BASS_ChannelPlay(_mixer, false);
            }
        }
コード例 #24
0
ファイル: BassPlayer.cs プロジェクト: ilynx/lmaml
        private void Setup()
        {
            if (!Bassh.BASS_Init(-1, sampleRate.Value, BASSInit.BASS_DEVICE_LATENCY | BASSInit.BASS_DEVICE_FREQ, IntPtr.Zero))
            {
                throw new InvalidOperationException("Could not initialize BASS");
            }
            Bassh.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATETHREADS, 4);
            Bassh.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, bufferSize.Value);
            Bassh.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, bufferSize.Value / 10);
            Trace.WriteLine(Bassh.BASS_GetInfo());
            var plugins = Bassh.BASS_PluginLoadDirectory(Environment.CurrentDirectory);

            mixerHandle = BassMix.BASS_Mixer_StreamCreate(sampleRate.Value, 2, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MIXER_NONSTOP);
            Bassh.BASS_ChannelPlay(mixerHandle, true);
            if (null == plugins)
            {
                return;
            }
            foreach (var plugin in plugins)
            {
                pluginHandles.Add(plugin.Key);
                logger.Log(LoggingType.Information, this, string.Format("Plugin Loaded: {0}", plugin.Value));
            }
        }
コード例 #25
0
        // メソッド

        public CSoundDeviceASIO(long n希望バッファサイズms, int _nASIODevice)
        {
            // 初期化。

            Trace.TraceInformation("BASS (ASIO) の初期化を開始します。");
            this.e出力デバイス            = ESoundDeviceType.Unknown;
            this.n実出力遅延ms           = 0;
            this.n経過時間ms            = 0;
            this.n経過時間を更新したシステム時刻ms = CTimer.n未使用;
            this.tmシステムタイマ          = new CTimer();
            this.nASIODevice        = _nASIODevice;

            #region [ BASS registration ]
            // BASS.NET ユーザ登録(BASSスプラッシュが非表示になる)。
            BassNet.Registration("*****@*****.**", "2X9181017152222");
            #endregion

            #region [ BASS Version Check ]
            // BASS のバージョンチェック。
            int nBASSVersion = Utils.HighWord(Bass.BASS_GetVersion());
            if (nBASSVersion != Bass.BASSVERSION)
            {
                throw new DllNotFoundException(string.Format("bass.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSVersion, Bass.BASSVERSION));
            }

            int nBASSMixVersion = Utils.HighWord(BassMix.BASS_Mixer_GetVersion());
            if (nBASSMixVersion != BassMix.BASSMIXVERSION)
            {
                throw new DllNotFoundException(string.Format("bassmix.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSMixVersion, BassMix.BASSMIXVERSION));
            }

            int nBASSASIO = Utils.HighWord(BassAsio.BASS_ASIO_GetVersion());
            if (nBASSASIO != BassAsio.BASSASIOVERSION)
            {
                throw new DllNotFoundException(string.Format("bassasio.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSASIO, BassAsio.BASSASIOVERSION));
            }
            #endregion

            // BASS の設定。

            this.bIsBASSFree = true;

            if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0))           // 0:BASSストリームの自動更新を行わない。
            {
                Trace.TraceWarning($"BASS_SetConfig({nameof(BASSConfig.BASS_CONFIG_UPDATEPERIOD)}) に失敗しました。[{Bass.BASS_ErrorGetCode()}]");
            }
            if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATETHREADS, 0))           // 0:BASSストリームの自動更新を行わない。
            {
                Trace.TraceWarning($"BASS_SetConfig({nameof(BASSConfig.BASS_CONFIG_UPDATETHREADS)}) に失敗しました。[{Bass.BASS_ErrorGetCode()}]");
            }

            // BASS の初期化。

            int nデバイス = 0;                      // 0:"no device" … BASS からはデバイスへアクセスさせない。アクセスは BASSASIO アドオンから行う。
            int n周波数  = 44100;                  // 仮決め。最終的な周波数はデバイス(≠ドライバ)が決める。
            if (!Bass.BASS_Init(nデバイス, n周波数, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero))
            {
                throw new Exception(string.Format("BASS の初期化に失敗しました。(BASS_Init)[{0}]", Bass.BASS_ErrorGetCode().ToString()));
            }

            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_CURVE_VOL, true);

//Debug.WriteLine( "BASS_Init()完了。" );
            #region [ デバッグ用: ASIOデバイスのenumerateと、ログ出力 ]
//			CEnumerateAllAsioDevices.GetAllASIODevices();
//Debug.WriteLine( "BassAsio.BASS_ASIO_GetDeviceInfo():" );
//            int a, count = 0;
//            BASS_ASIO_DEVICEINFO asioDevInfo;
//            for ( a = 0; ( asioDevInfo = BassAsio.BASS_ASIO_GetDeviceInfo( a ) ) != null; a++ )
//            {
//                Trace.TraceInformation( "ASIO Device {0}: {1}, driver={2}", a, asioDevInfo.name, asioDevInfo.driver );
//                count++; // count it
//            }
            #endregion

            // BASS ASIO の初期化。
            BASS_ASIO_INFO asioInfo = null;
            if (BassAsio.BASS_ASIO_Init(nASIODevice, BASSASIOInit.BASS_ASIO_THREAD))                    // 専用スレッドにて起動
            {
                #region [ ASIO の初期化に成功。]
                //-----------------
                this.e出力デバイス           = ESoundDeviceType.ASIO;
                asioInfo               = BassAsio.BASS_ASIO_GetInfo();
                this.n出力チャンネル数         = asioInfo.outputs;
                this.db周波数             = BassAsio.BASS_ASIO_GetRate();
                this.fmtASIOデバイスフォーマット = BassAsio.BASS_ASIO_ChannelGetFormat(false, 0);

                Trace.TraceInformation("BASS を初期化しました。(ASIO, デバイス:\"{0}\", 入力{1}, 出力{2}, {3}Hz, バッファ{4}~{6}sample ({5:0.###}~{7:0.###}ms), デバイスフォーマット:{8})",
                                       asioInfo.name,
                                       asioInfo.inputs,
                                       asioInfo.outputs,
                                       this.db周波数.ToString("0.###"),
                                       asioInfo.bufmin, asioInfo.bufmin * 1000 / this.db周波数,
                                       asioInfo.bufmax, asioInfo.bufmax * 1000 / this.db周波数,
                                       this.fmtASIOデバイスフォーマット.ToString()
                                       );
                this.bIsBASSFree = false;
                #region [ debug: channel format ]
                //BASS_ASIO_CHANNELINFO chinfo = new BASS_ASIO_CHANNELINFO();
                //int chan = 0;
                //while ( true )
                //{
                //    if ( !BassAsio.BASS_ASIO_ChannelGetInfo( false, chan, chinfo ) )
                //        break;
                //    Debug.WriteLine( "Ch=" + chan + ": " + chinfo.name.ToString() + ", " + chinfo.group.ToString() + ", " + chinfo.format.ToString() );
                //    chan++;
                //}
                #endregion
                //-----------------
                #endregion
            }
            else
            {
                #region [ ASIO の初期化に失敗。]
                //-----------------
                BASSError errcode = Bass.BASS_ErrorGetCode();
                string    errmes  = errcode.ToString();
                if (errcode == BASSError.BASS_OK)
                {
                    errmes = "BASS_OK; The device may be dissconnected";
                }
                Bass.BASS_Free();
                this.bIsBASSFree = true;
                throw new Exception(string.Format("BASS (ASIO) の初期化に失敗しました。(BASS_ASIO_Init)[{0}]", errmes));
                //-----------------
                #endregion
            }


            // ASIO 出力チャンネルの初期化。

            this.tAsioProc = new ASIOPROC(this.tAsio処理);                                  // アンマネージに渡す delegate は、フィールドとして保持しておかないとGCでアドレスが変わってしまう。
            if (!BassAsio.BASS_ASIO_ChannelEnable(false, 0, this.tAsioProc, IntPtr.Zero)) // 出力チャンネル0 の有効化。
            {
                #region [ ASIO 出力チャンネルの初期化に失敗。]
                //-----------------
                BassAsio.BASS_ASIO_Free();
                Bass.BASS_Free();
                this.bIsBASSFree = true;
                throw new Exception(string.Format("Failed BASS_ASIO_ChannelEnable() [{0}]", BassAsio.BASS_ASIO_ErrorGetCode().ToString()));
                //-----------------
                #endregion
            }
            for (int i = 1; i < this.n出力チャンネル数; i++)                            // 出力チャネルを全てチャネル0とグループ化する。
            {                                                                   // チャネル1だけを0とグループ化すると、3ch以上の出力をサポートしたカードでの動作がおかしくなる
                if (!BassAsio.BASS_ASIO_ChannelJoin(false, i, 0))
                {
                    #region [ 初期化に失敗。]
                    //-----------------
                    BassAsio.BASS_ASIO_Free();
                    Bass.BASS_Free();
                    this.bIsBASSFree = true;
                    throw new Exception(string.Format("Failed BASS_ASIO_ChannelJoin({1}) [{0}]", BassAsio.BASS_ASIO_ErrorGetCode().ToString(), i));
                    //-----------------
                    #endregion
                }
            }
            if (!BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, this.fmtASIOチャンネルフォーマット))                        // 出力チャンネル0のフォーマット
            {
                #region [ ASIO 出力チャンネルの初期化に失敗。]
                //-----------------
                BassAsio.BASS_ASIO_Free();
                Bass.BASS_Free();
                this.bIsBASSFree = true;
                throw new Exception(string.Format("Failed BASS_ASIO_ChannelSetFormat() [{0}]", BassAsio.BASS_ASIO_ErrorGetCode().ToString()));
                //-----------------
                #endregion
            }

            // ASIO 出力と同じフォーマットを持つ BASS ミキサーを作成。

            var flag = BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_STREAM_DECODE;               // デコードのみ=発声しない。ASIO に出力されるだけ。
            if (this.fmtASIOデバイスフォーマット == BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT)
            {
                flag |= BASSFlag.BASS_SAMPLE_FLOAT;
            }
            this.hMixer = BassMix.BASS_Mixer_StreamCreate((int)this.db周波数, this.n出力チャンネル数, flag);

            if (this.hMixer == 0)
            {
                BASSError err = Bass.BASS_ErrorGetCode();
                BassAsio.BASS_ASIO_Free();
                Bass.BASS_Free();
                this.bIsBASSFree = true;
                throw new Exception(string.Format("BASSミキサ(mixing)の作成に失敗しました。[{0}]", err));
            }

            // BASS ミキサーの1秒あたりのバイト数を算出。

            var mixerInfo    = Bass.BASS_ChannelGetInfo(this.hMixer);
            int nサンプルサイズbyte = 0;
            switch (this.fmtASIOチャンネルフォーマット)
            {
            case BASSASIOFormat.BASS_ASIO_FORMAT_16BIT: nサンプルサイズbyte = 2; break;

            case BASSASIOFormat.BASS_ASIO_FORMAT_24BIT: nサンプルサイズbyte = 3; break;

            case BASSASIOFormat.BASS_ASIO_FORMAT_32BIT: nサンプルサイズbyte = 4; break;

            case BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT: nサンプルサイズbyte = 4; break;
            }
            //long nミキサーの1サンプルあたりのバイト数 = /*mixerInfo.chans*/ 2 * nサンプルサイズbyte;
            long nミキサーの1サンプルあたりのバイト数 = mixerInfo.chans * nサンプルサイズbyte;
            this.nミキサーの1秒あたりのバイト数 = nミキサーの1サンプルあたりのバイト数 * mixerInfo.freq;


            // 単純に、hMixerの音量をMasterVolumeとして制御しても、
            // ChannelGetData()の内容には反映されない。
            // そのため、もう一段mixerを噛ませて、一段先のmixerからChannelGetData()することで、
            // hMixerの音量制御を反映させる。
            this.hMixer_DeviceOut = BassMix.BASS_Mixer_StreamCreate(
                (int)this.db周波数, this.n出力チャンネル数, flag);
            if (this.hMixer_DeviceOut == 0)
            {
                BASSError errcode = Bass.BASS_ErrorGetCode();
                BassAsio.BASS_ASIO_Free();
                Bass.BASS_Free();
                this.bIsBASSFree = true;
                throw new Exception(string.Format("BASSミキサ(最終段)の作成に失敗しました。[{0}]", errcode));
            }
            {
                bool b1 = BassMix.BASS_Mixer_StreamAddChannel(this.hMixer_DeviceOut, this.hMixer, BASSFlag.BASS_DEFAULT);
                if (!b1)
                {
                    BASSError errcode = Bass.BASS_ErrorGetCode();
                    BassAsio.BASS_ASIO_Free();
                    Bass.BASS_Free();
                    this.bIsBASSFree = true;
                    throw new Exception(string.Format("BASSミキサ(最終段とmixing)の接続に失敗しました。[{0}]", errcode));
                }
                ;
            }


            // 出力を開始。

            this.nバッファサイズsample = (int)(n希望バッファサイズms * this.db周波数 / 1000.0);
            //this.nバッファサイズsample = (int)  nバッファサイズbyte;
            if (!BassAsio.BASS_ASIO_Start(this.nバッファサイズsample))                         // 範囲外の値を指定した場合は自動的にデフォルト値に設定される。
            {
                BASSError err = BassAsio.BASS_ASIO_ErrorGetCode();
                BassAsio.BASS_ASIO_Free();
                Bass.BASS_Free();
                this.bIsBASSFree = true;
                throw new Exception("ASIO デバイス出力開始に失敗しました。" + err.ToString());
            }
            else
            {
                int n遅延sample   = BassAsio.BASS_ASIO_GetLatency(false);                 // この関数は BASS_ASIO_Start() 後にしか呼び出せない。
                int n希望遅延sample = (int)(n希望バッファサイズms * this.db周波数 / 1000.0);
                this.n実バッファサイズms = this.n実出力遅延ms = (long)(n遅延sample * 1000.0f / this.db周波数);
                Trace.TraceInformation("ASIO デバイス出力開始:バッファ{0}sample(希望{1}) [{2}ms(希望{3}ms)]", n遅延sample, n希望遅延sample, this.n実出力遅延ms, n希望バッファサイズms);
            }
        }
コード例 #26
0
ファイル: MixerStream.cs プロジェクト: jgrumboe/MediaPortal-1
        /// <summary>
        /// Create a mixer using the stream attributes
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public bool CreateMixer(MusicStream stream)
        {
            Log.Debug("BASS: ---------------------------------------------");
            Log.Debug("BASS: Creating BASS mixer stream");

            bool result = false;

            BASSFlag mixerFlags = BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MIXER_NORAMPIN;

            if (Config.MusicPlayer == AudioPlayer.Asio || Config.MusicPlayer == AudioPlayer.WasApi)
            {
                mixerFlags |= BASSFlag.BASS_STREAM_DECODE;
            }

            int outputChannels = _bassPlayer.DeviceChannels;

            _mixingMatrix = null;

            // See, if we need Upmixing
            if (outputChannels > stream.ChannelInfo.chans)
            {
                Log.Debug("BASS: Found more output channels ({0}) than input channels ({1}). Check for upmixing.", outputChannels,
                          stream.ChannelInfo.chans);
                _mixingMatrix = CreateMixingMatrix(stream.ChannelInfo.chans);
                if (_mixingMatrix != null)
                {
                    outputChannels = Math.Min(_mixingMatrix.GetLength(0), outputChannels);
                    _upmixing      = true;
                }
                else
                {
                    outputChannels = stream.ChannelInfo.chans;
                }
            }
            else if (outputChannels < stream.ChannelInfo.chans)
            {
                // Downmix to Stereo
                Log.Debug("BASS: Found more input channels ({0}) than output channels ({1}). Downmix.", stream.ChannelInfo.chans,
                          outputChannels);
                outputChannels = Math.Min(outputChannels, 2);
            }

            Log.Debug("BASS: Creating {0} channel mixer with sample rate of {1}", outputChannels, stream.ChannelInfo.freq);
            _mixer = BassMix.BASS_Mixer_StreamCreate(stream.ChannelInfo.freq, outputChannels, mixerFlags);
            if (_mixer == 0)
            {
                Log.Error("BASS: Unable to create Mixer.  Reason: {0}.",
                          Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                return(false);
            }

            switch (Config.MusicPlayer)
            {
            case AudioPlayer.Bass:
            case AudioPlayer.DShow:

                if (!Bass.BASS_ChannelPlay(_mixer, false))
                {
                    Log.Error("BASS: Unable to start Mixer.  Reason: {0}.", Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                    return(false);
                }

                result = true;

                break;

            case AudioPlayer.Asio:

                Log.Info("BASS: Initialising ASIO device");

                if (BassAsio.BASS_ASIO_IsStarted() && !BassAsio.BASS_ASIO_Stop())
                {
                    Log.Error("BASS: Error stopping Asio Device: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // Disable and Unjoin all the channels
                if (!BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_ENABLE))
                {
                    Log.Error("BASS: Error disabling Asio Channels: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                if (!BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_JOIN))
                {
                    Log.Error("BASS: Error unjoining Asio Channels: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                _asioProc = new ASIOPROC(AsioCallback);

                BassAsio.BASS_ASIO_ChannelSetVolume(false, -1, (float)Config.StreamVolume / 100f);

                // enable 1st output channel...(0=first)
                Log.Debug("BASS: Joining Asio Channel #{0}", "0");
                BassAsio.BASS_ASIO_ChannelEnable(false, 0, _asioProc, new IntPtr(_mixer));

                // and join the next channels to it
                int numChannels = Math.Max(stream.ChannelInfo.chans, outputChannels);
                for (int i = 1; i < numChannels; i++)
                {
                    Log.Debug("BASS: Joining Asio Channel #{0}", i);
                    BassAsio.BASS_ASIO_ChannelJoin(false, i, 0);
                }

                // since we joined the channels, the next commands will apply to all channles joined
                // so setting the values to the first channels changes them all automatically
                // set the source format (float, as the decoding channel is)
                if (!BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT))
                {
                    Log.Error("BASS: Error setting Asio Sample Format: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // set the source rate
                Log.Debug("BASS: Set sample rate to {0}", stream.ChannelInfo.freq);
                if (!BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)stream.ChannelInfo.freq))
                {
                    Log.Error("BASS: Error setting Asio Channel Samplerate: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // try to set the device rate too (saves resampling)
                if (!BassAsio.BASS_ASIO_SetRate((double)stream.ChannelInfo.freq))
                {
                    Log.Error("BASS: Error setting Asio Samplerate: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // and start playing it...start output using default buffer/latency
                if (!BassAsio.BASS_ASIO_Start(0))
                {
                    Log.Error("BASS: Error starting Asio playback: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }
                Log.Info("BASS: Finished initialising ASIO device");
                result = true;

                break;

            case AudioPlayer.WasApi:

                Log.Info("BASS: Initialising WASAPI device");

                try
                {
                    BassWasapi.BASS_WASAPI_Free();
                    Log.Debug("BASS: Freed WASAPI device");
                }
                catch (Exception ex)
                {
                    Log.Error("BASS: Exception freeing WASAPI. {0} {1}", ex.Message, ex.StackTrace);
                }

                BASSWASAPIInit initFlags = BASSWASAPIInit.BASS_WASAPI_AUTOFORMAT;

                _wasapiProc = new WASAPIPROC(WasApiCallback);

                bool wasApiExclusiveSupported = true;

                // Check if we have an uneven number of channels
                var chkChannels = outputChannels % 2;
                if (chkChannels == 1)
                {
                    Log.Warn("BASS: Found uneven number of channels {0}. increase output channels.", outputChannels);
                    outputChannels++;                 // increase the number of output channels
                    wasApiExclusiveSupported = false; // And indicate that we need a new mixer
                }

                // Handle the special cases of 3.0, 4.0 and 5.0 files being played on a 5.1 or 6.1 device
                if (outputChannels == 3) // a 3.0 file
                {
                    Log.Info("BASS: Found a 3 channel file. Set upmixing with LFE, LR, RR set to silent");
                    _mixingMatrix            = CreateThreeDotZeroUpMixMatrix();
                    outputChannels           = _bassPlayer.DeviceChannels; // WASAPI device should be initialised with all channels active
                    wasApiExclusiveSupported = false;                      // And indicate that we need a new mixer
                }
                else if (outputChannels == 4)                              // a 4.0 file
                {
                    Log.Info("BASS: Found a 4 channel file. Set upmixing with Center and LFE set to silent");
                    _mixingMatrix            = CreateFourDotZeroUpMixMatrix();
                    outputChannels           = _bassPlayer.DeviceChannels; // WASAPI device should be initialised with all channels active
                    wasApiExclusiveSupported = false;                      // And indicate that we need a new mixer
                }
                else if (outputChannels == 5)                              // a 5.0 file
                {
                    Log.Info("BASS: Found a 5 channel file. Set upmixing with LFE set to silent");
                    _mixingMatrix            = CreateFiveDotZeroUpMixMatrix();
                    outputChannels           = _bassPlayer.DeviceChannels; // WASAPI device should be initialised with all channels active
                    wasApiExclusiveSupported = false;                      // And indicate that we need a new mixer
                }

                // If Exclusive mode is used, check, if that would be supported, otherwise init in shared mode
                if (Config.WasApiExclusiveMode)
                {
                    initFlags        |= BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE;
                    _wasapiShared     = false;
                    _wasapiMixedChans = 0;
                    _wasapiMixedFreq  = 0;

                    BASSWASAPIFormat wasapiFormat = BassWasapi.BASS_WASAPI_CheckFormat(_bassPlayer.DeviceNumber,
                                                                                       stream.ChannelInfo.freq,
                                                                                       outputChannels,
                                                                                       BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE);
                    if (wasapiFormat == BASSWASAPIFormat.BASS_WASAPI_FORMAT_UNKNOWN)
                    {
                        Log.Warn("BASS: WASAPI exclusive mode not directly supported. Let BASS WASAPI choose better mode.");
                        wasApiExclusiveSupported = false;
                    }
                }
                else
                {
                    Log.Debug("BASS: Init WASAPI shared mode with Event driven system enabled.");
                    initFlags |= BASSWASAPIInit.BASS_WASAPI_SHARED | BASSWASAPIInit.BASS_WASAPI_EVENT;

                    // In case of WASAPI Shared mode we need to setup the mixer to use the same sample rate as set in
                    // the Windows Mixer, otherwise we wioll have increased playback speed
                    BASS_WASAPI_DEVICEINFO devInfo = BassWasapi.BASS_WASAPI_GetDeviceInfo(_bassPlayer.DeviceNumber);
                    Log.Debug("BASS: Creating {0} channel mixer for frequency {1}", devInfo.mixchans, devInfo.mixfreq);
                    _mixer = BassMix.BASS_Mixer_StreamCreate(devInfo.mixfreq, devInfo.mixchans, mixerFlags);
                    if (_mixer == 0)
                    {
                        Log.Error("BASS: Unable to create Mixer.  Reason: {0}.",
                                  Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                        return(false);
                    }
                    _wasapiShared = true;
                }

                Log.Debug("BASS: Try to init WASAPI with a Frequency of {0} and {1} channels", stream.ChannelInfo.freq, outputChannels);

                if (BassWasapi.BASS_WASAPI_Init(_bassPlayer.DeviceNumber, stream.ChannelInfo.freq, outputChannels,
                                                initFlags | BASSWASAPIInit.BASS_WASAPI_BUFFER, Convert.ToSingle(Config.BufferingMs / 1000.0), 0f, _wasapiProc, IntPtr.Zero))
                {
                    BASS_WASAPI_INFO wasapiInfo = BassWasapi.BASS_WASAPI_GetInfo();

                    Log.Debug("BASS: ---------------------------------------------");
                    Log.Debug("BASS: Buffer Length: {0}", wasapiInfo.buflen);
                    Log.Debug("BASS: Channels: {0}", wasapiInfo.chans);
                    Log.Debug("BASS: Frequency: {0}", wasapiInfo.freq);
                    Log.Debug("BASS: Format: {0}", wasapiInfo.format.ToString());
                    Log.Debug("BASS: InitFlags: {0}", wasapiInfo.initflags.ToString());
                    Log.Debug("BASS: Exclusive: {0}", wasapiInfo.IsExclusive.ToString());
                    Log.Debug("BASS: ---------------------------------------------");
                    Log.Info("BASS: WASAPI Device successfully initialised");

                    // Now we need to check, if WASAPI decided to switch to a different mode
                    if (Config.WasApiExclusiveMode && !wasApiExclusiveSupported)
                    {
                        // Recreate Mixer with new value
                        Log.Debug("BASS: Creating new {0} channel mixer for frequency {1}", wasapiInfo.chans, wasapiInfo.freq);
                        _mixer = BassMix.BASS_Mixer_StreamCreate(wasapiInfo.freq, wasapiInfo.chans, mixerFlags);
                        if (_mixer == 0)
                        {
                            Log.Error("BASS: Unable to create Mixer.  Reason: {0}.",
                                      Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                            return(false);
                        }
                    }

                    BassWasapi.BASS_WASAPI_SetVolume(BASSWASAPIVolume.BASS_WASAPI_CURVE_DB, (float)Config.StreamVolume / 100f);
                    BassWasapi.BASS_WASAPI_Start();
                    result = true;
                }
                else
                {
                    Log.Error("BASS: Couldn't init WASAPI device. Error: {0}", Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                }
                break;
            }

            if (result)
            {
                Log.Debug("BASS: Successfully created BASS Mixer stream");
            }
            return(result);
        }
コード例 #27
0
        private void ProcessStreamData(byte[] buffer, int offset, int length)
        {
            if (length < 1)
            {
                return;
            }

            // Write compressed audio data to Circulairbuffer
            byte[] data = new byte[length];
            Buffer.BlockCopy(buffer, offset, data, 0, length);
            lock (lockObject)
            {
                cbbChunkAudio.Write(buffer, offset, length);
            }


            // If basshandle wasn't opened then open it now (when there is enough data. Min 4010 bytes)
            if (inputHandle == 0 && cbbChunkAudio.UsedBytes >= 8000)
            {
                // bass needs for mp3 atleast 4000 bytes before is can play
                inputHandle = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_BUFFERPUSH, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT, bassFileProcs, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelSetSync(inputHandle, BASSSync.BASS_SYNC_STALL, 0, bassStalledSync, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelSetSync(inputHandle, BASSSync.BASS_SYNC_END, 0, bassEndSync, GCHandle.ToIntPtr((GCHandle)gcHandle));

                mixerHandle = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
                BassMix.BASS_Mixer_StreamAddChannel(mixerHandle, inputHandle, BASSFlag.BASS_MIXER_FILTER | BASSFlag.BASS_MIXER_DOWNMIX);
                Bass.BASS_ChannelPlay(inputHandle, false);
                Bass.BASS_ChannelPlay(mixerHandle, false);
                return;
            }

            // push new audiodata when available (and basstream is opened)
            if (inputHandle != 0)
            {
                // voed bass met audio data zodat deze het naar pcm data kan decompressen
                long bassBufLen = Bass.BASS_StreamGetFilePosition(inputHandle, BASSStreamFilePosition.BASS_FILEPOS_END);
                long bassBufPos = Bass.BASS_StreamGetFilePosition(inputHandle, BASSStreamFilePosition.BASS_FILEPOS_BUFFER);
                int  todo       = Convert.ToInt32(bassBufLen - bassBufPos);
                if (todo > 0)
                {
                    int count      = todo;
                    int writeBytes = 0;
                    while (!cbbChunkAudio.IsEmpty && todo > 0 && writeBytes > -1)
                    {
                        if (count > 16384)
                        {
                            count = 16384;
                        }
                        byte[] tmpBuffer = new byte[count];
                        lock (lockObject)
                        {
                            count = cbbChunkAudio.Read(tmpBuffer, count);
                        }
                        if (count > 0)
                        {
                            writeBytes = Bass.BASS_StreamPutFileData(inputHandle, tmpBuffer, count);
                            todo      -= writeBytes;
                        }
                    } //while audio buffer not empty
                }
                ProcessDecompressedData();
            }
        }
コード例 #28
0
 public int CreateMixerStream(int sampleRate, int channels, BASSFlag flags)
 {
     return(BassMix.BASS_Mixer_StreamCreate(sampleRate, channels, flags));
 }
コード例 #29
0
        public override void SetInputStream(BassStream stream, bool passThrough)
        {
            if (_deviceState != DeviceState.Stopped)
            {
                throw new BassPlayerException("Device state is not 'DeviceState.Stopped'");
            }

            _inputStream = stream;
            _flags       = BASSWASAPIInit.BASS_WASAPI_AUTOFORMAT | BASSWASAPIInit.BASS_WASAPI_BUFFER;

            // If Exclusive mode is used, check, if that would be supported, otherwise init in shared mode
            bool isExclusive = Controller.GetSettings().WASAPIExclusiveMode;

            if (isExclusive)
            {
                _flags |= BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE;

                BASSWASAPIFormat wasapiFormat = BassWasapi.BASS_WASAPI_CheckFormat(_deviceNo,
                                                                                   _inputStream.SampleRate,
                                                                                   _inputStream.Channels,
                                                                                   BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE);
                if (wasapiFormat == BASSWASAPIFormat.BASS_WASAPI_FORMAT_UNKNOWN)
                {
                    Log.Info("BASS: WASAPI exclusive mode not directly supported for samplerate of {0} and {1} channels", _inputStream.SampleRate, _inputStream.Channels);
                    isExclusive = false;
                }
            }

retry:
            if (!isExclusive)
            {
                Log.Debug("BASS: Init WASAPI shared mode with Event driven system enabled.");
                _flags &= ~BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE;
                _flags |= BASSWASAPIInit.BASS_WASAPI_SHARED | BASSWASAPIInit.BASS_WASAPI_EVENT;
            }

            Log.Debug("BASS: Try to init WASAPI with a samplerate of {0} and {1} channels", _inputStream.SampleRate, _inputStream.Channels);

            bool result = BassWasapi.BASS_WASAPI_Init(_deviceNo, _inputStream.SampleRate, _inputStream.Channels, _flags, 0.5f, 0f, _streamWriteProcDelegate, IntPtr.Zero);

            BASSError?bassInitErrorCode = result ? null : new BASSError?(Bass.BASS_ErrorGetCode());

            if (bassInitErrorCode.HasValue)
            {
                if (bassInitErrorCode.Value == BASSError.BASS_ERROR_ALREADY)
                {
                    if (!BassWasapi.BASS_WASAPI_SetDevice(_deviceNo))
                    {
                        throw new BassLibraryException("BASS_WASAPI_SetDevice");
                    }
                }
                else if (isExclusive)
                {
                    // Allow one retry in shared mode
                    Log.Warn("BASS: Failed to initialize WASAPI exclusive mode for samplerate of {0} and {1} channels. Trying fallback to shared mode.", _inputStream.SampleRate, _inputStream.Channels);
                    isExclusive = false;
                    goto retry;
                }
                else
                {
                    throw new BassLibraryException("BASS_WASAPI_Init");
                }
            }

            // If the GetDeviceNo() method returned BassConstants.BassDefaultDevice, we must request the actual device number
            // of the choosen default device
            _deviceNo = BassWasapi.BASS_WASAPI_GetDevice();

            CollectDeviceInfo(_deviceNo);
            BASS_WASAPI_INFO wasapiInfo = BassWasapi.BASS_WASAPI_GetInfo();

            Log.Debug("BASS: ---------------------------------------------");
            Log.Debug("BASS: Buffer Length: {0}", wasapiInfo.buflen);
            Log.Debug("BASS: Channels: {0}", wasapiInfo.chans);
            Log.Debug("BASS: Frequency: {0}", wasapiInfo.freq);
            Log.Debug("BASS: Format: {0}", wasapiInfo.format.ToString());
            Log.Debug("BASS: InitFlags: {0}", wasapiInfo.initflags.ToString());
            Log.Debug("BASS: Exclusive: {0}", wasapiInfo.IsExclusive.ToString());
            Log.Debug("BASS: ---------------------------------------------");
            Log.Info("BASS: WASAPI Device successfully initialised");

            // For shared mode we require a mixer to change the sampling rates of input stream to device output stream.
            if (!wasapiInfo.IsExclusive)
            {
                // Recreate Mixer with new value
                Log.Debug("BASS: Creating new {0} channel mixer for frequency {1}", wasapiInfo.chans, wasapiInfo.freq);
                _mixerHandle = BassMix.BASS_Mixer_StreamCreate(wasapiInfo.freq, wasapiInfo.chans, MIXER_FLAGS);
                if (_mixerHandle == BassConstants.BassInvalidHandle)
                {
                    throw new BassLibraryException("BASS_Mixer_StreamCreate");
                }
                _mixer = BassStream.Create(_mixerHandle);
                AttachStream();
            }

            int ms = Convert.ToInt32(Controller.GetSettings().DirectSoundBufferSize.TotalMilliseconds);

            if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, ms))
            {
                throw new BassLibraryException("BASS_SetConfig");
            }

            // Enable update thread while the output device is active
            if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, ms / 4))
            {
                throw new BassLibraryException("BASS_SetConfig");
            }

            if (passThrough)
            {
                _fader = new BassStreamFader(_inputStream, Controller.GetSettings().FadeDuration);
            }

            ResetState();
        }
コード例 #30
0
        /// <summary>
        ///   Read mono from file
        /// </summary>
        /// <param name = "filename">Name of the file</param>
        /// <param name = "samplerate">Sample rate</param>
        /// <param name = "milliseconds">milliseconds to read</param>
        /// <param name = "startmillisecond">Start millisecond</param>
        /// <returns>Array of samples</returns>
        public float[] ReadMonoFromFile(string filename, int samplerate, int milliseconds, int startmillisecond)
        {
            int totalmilliseconds = milliseconds <= 0 ? Int32.MaxValue : milliseconds + startmillisecond;

            float[] data = null;
            //create streams for re-sampling
            int stream = Un4seen.Bass.Bass.BASS_StreamCreateFile(filename, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_MONO | BASSFlag.BASS_SAMPLE_FLOAT);             //Decode the stream

            if (stream == 0)
            {
                throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString());
            }
            int mixerStream = BassMix.BASS_Mixer_StreamCreate(samplerate, 1, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_MONO | BASSFlag.BASS_SAMPLE_FLOAT);

            if (mixerStream == 0)
            {
                throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString());
            }

            if (BassMix.BASS_Mixer_StreamAddChannel(mixerStream, stream, BASSFlag.BASS_MIXER_FILTER))
            {
                const int      bufferSize = 5512 * 10 * 4;        /*read ten seconds at each iteration*/
                float[]        buffer     = new float[bufferSize];
                List <float[]> chunks     = new List <float[]>();
                int            size       = 0;
                while ((float)(size) / samplerate * 1000 < totalmilliseconds)
                {
                    //get re-sampled/mono data
                    int bytesRead = Un4seen.Bass.Bass.BASS_ChannelGetData(mixerStream, buffer, bufferSize);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    float[] chunk = new float[bytesRead / 4];                   //each float contains 4 bytes
                    Array.Copy(buffer, chunk, bytesRead / 4);
                    chunks.Add(chunk);
                    size += bytesRead / 4;                   //size of the data
                }

                if ((float)(size) / samplerate * 1000 < (milliseconds + startmillisecond))
                {
                    return(null);                    /*not enough samples to return the requested data*/
                }
                int start = (int)((float)startmillisecond * samplerate / 1000);
                int end   = (milliseconds <= 0) ? size : (int)((float)(startmillisecond + milliseconds) * samplerate / 1000);
                data = new float[size];
                int index = 0;
                /*Concatenate*/
                foreach (float[] chunk in chunks)
                {
                    Array.Copy(chunk, 0, data, index, chunk.Length);
                    index += chunk.Length;
                }
                /*Select specific part of the song*/
                if (start != 0 || end != size)
                {
                    float[] temp = new float[end - start];
                    Array.Copy(data, start, temp, 0, end - start);
                    data = temp;
                }
            }
            else
            {
                throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString());
            }
            return(data);
        }