private void asio_control_btn_Click(object sender, EventArgs e) { BassAsio.BASS_ASIO_ControlPanel(); }
/// <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); }
private void buttonPlay_Click(object sender, System.EventArgs e) { BassAsio.BASS_ASIO_Stop(); BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_PAUSE | BASSASIOReset.BASS_ASIO_RESET_JOIN); Bass.BASS_StreamFree(_streamFX); if (_fileName != String.Empty) { // create the decoding stream _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); if (_stream != 0) { // now we create a Tempo channel (again a decoding one)...the actual playing channel _streamFX = BassFx.BASS_FX_TempoCreate(_stream, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_FX_FREESOURCE | BASSFlag.BASS_SAMPLE_FLOAT); if (_streamFX == 0) { MessageBox.Show(this, "Can't create FX stream!", Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode())); return; } // now setup ASIO myAsioProc = new ASIOPROC(AsioCallback); // get the stream channel info BASS_CHANNELINFO info = new BASS_CHANNELINFO(); Bass.BASS_ChannelGetInfo(_streamFX, info); _originSampleRate = (float)info.freq; this.button2.Text = _originSampleRate.ToString("0"); // enable 1st output channel...(0=first) BassAsio.BASS_ASIO_ChannelEnable(false, 0, myAsioProc, new IntPtr(_streamFX)); // and join the next channels to it for (int a = 1; a < info.chans; a++) { BassAsio.BASS_ASIO_ChannelJoin(false, a, 0); } // since we joined the channels, the next commands will applay 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) BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT); // set the source rate BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)info.freq); // try to set the device rate too (saves resampling) BassAsio.BASS_ASIO_SetRate((double)info.freq); // and start playing it... // start output using default buffer/latency if (!BassAsio.BASS_ASIO_Start(0)) { MessageBox.Show(this, "Can't start ASIO output", Enum.GetName(typeof(BASSError), BassAsio.BASS_ASIO_ErrorGetCode())); } else { this.labelStatus.Text = "playing"; this.timerUpdate.Start(); } } } }
/// <summary> /// Get the sound devices for the selected Player /// </summary> /// <param name="player"> /// 0 - Bass Directshow /// 1 - ASIO /// 2 - WASAPI /// 3 - Internal Dshow Player /// </param> private void GetAvailableSoundDevices(int player) { switch (player) { case (int)AudioPlayer.Bass: case (int)AudioPlayer.DShow: // Get all available devices and add them to the combo box BASS_DEVICEINFO[] soundDevices = Bass.BASS_GetDeviceInfos(); // For Directshow player, we need to have the exact wording here if (audioPlayerComboBox.SelectedIndex == 1) { soundDeviceComboBox.Items.Add(new SoundDeviceItem("Default DirectSound Device", "")); } else { soundDeviceComboBox.Items.Add(new SoundDeviceItem("Default Sound Device", "")); } // Fill the combo box, starting at 1 to skip the "No Sound" device for (int i = 1; i < soundDevices.Length; i++) { soundDeviceComboBox.Items.Add(new SoundDeviceItem(soundDevices[i].name, soundDevices[i].id)); } break; case (int)AudioPlayer.Asio: // Get all available ASIO devices and add them to the combo box BASS_ASIO_DEVICEINFO[] asioDevices = BassAsio.BASS_ASIO_GetDeviceInfos(); if (asioDevices.Length == 0) { MessageBox.Show(this, "No ASIO Devices available in the system.", "MediaPortal - Setup", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); // Default back to BASS Player audioPlayerComboBox.SelectedIndex = 0; } else { foreach (BASS_ASIO_DEVICEINFO deviceInfo in asioDevices) { soundDeviceComboBox.Items.Add(new SoundDeviceItem(deviceInfo.name, deviceInfo.driver)); } } break; case (int)AudioPlayer.WasApi: // Get all available ASIO devices and add them to the combo box BASS_WASAPI_DEVICEINFO[] wasapiDevices = BassWasapi.BASS_WASAPI_GetDeviceInfos(); if (wasapiDevices.Length == 0) { MessageBox.Show(this, "No WASAPI Devices available in the system.", "MediaPortal - Setup", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); // Default back to BASS Player audioPlayerComboBox.SelectedIndex = 0; } else { foreach (BASS_WASAPI_DEVICEINFO deviceInfo in wasapiDevices) { // Only add enabled and output devices to the list if (deviceInfo.IsEnabled && !deviceInfo.IsInput) { soundDeviceComboBox.Items.Add(new SoundDeviceItem(deviceInfo.name, deviceInfo.id)); } } } if (soundDeviceComboBox.Items.Count == 0) { // Add default sound device to avoid crash. soundDeviceComboBox.Items.Add(new SoundDeviceItem("Default Sound Device", "")); soundDeviceComboBox.Items[0] = new SoundDeviceItem("Default Sound Device", ""); } break; } }
private void DeviceCP_Click(object sender, EventArgs e) { BassAsio.BASS_ASIO_ControlPanel(); }
// the main ASIO callback - filling the ASIO buffer with sample data to play... private int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) { // Note: 'user' contains the underlying stream channel (_streamFX) // get the status of the playing channel...(Note: you can do this also with a SYNCPORC)! _status = Bass.BASS_ChannelIsActive(user.ToInt32()); // now we evaluate the status... if (_status == BASSActive.BASS_ACTIVE_STOPPED) { // if the playing channel is at the end, we pause ASIO // Note: you need to call BASS_ASIO_ChannelReset to resume the ASIO channel! BassAsio.BASS_ASIO_ChannelPause(false, channel); this.BeginInvoke(new UpdateMessageDelegate(UpdateMessageDisplay), new object[] { "stopped" }); return(0); } else if (_status == BASSActive.BASS_ACTIVE_PAUSED || _status == BASSActive.BASS_ACTIVE_STALLED) { this.BeginInvoke(new UpdateMessageDelegate(UpdateMessageDisplay), new object[] { "paused" }); return(0); } else { // if playing, we just get the data from our decoding channel // Note: a decoding channel will be 'advanced' automatically, // so the next call to the decoding channel will get the next data... _decLength = Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length); // however, it might be the case, that BASS_ChannelGetData returned less data than requested if (_decLength < 0) { _decLength = 0; } } // from here on we deal with our buffer...calculating the peak VU int l4 = _decLength / 4; _maxL = 0; _maxR = 0; unsafe { float *data = (float *)buffer; for (a = 0; a < l4; a++) { // decide on L/R channel if (a % 2 == 0) { // L channel if (data[a] > _maxL) { _maxL = data[a]; } } else { // R channel if (data[a] > _maxR) { _maxR = data[a]; } } } } // limit the maximum peak levels to 0bB = 32768 // and a float value of 1.0 also represents 0db. _peakL = (int)Math.Round(32768f * _maxL); if (_peakL > 32768) { _peakL = 32768; } _peakR = (int)Math.Round(32768f * _maxR); if (_peakR > 32768) { _peakR = 32768; } return(_decLength); }
public void Test001() { if (!Bass.Init(Bass.NoSoundDevice)) { Assert.Fail(string.Format("Failed to initialize BASS: {0}", Enum.GetName(typeof(Errors), Bass.LastError))); } if (!BassAsio.Init(2, AsioInitFlags.Thread)) { Assert.Fail(string.Format("Failed to initialize ASIO: {0}", Enum.GetName(typeof(Errors), BassAsio.LastError))); } if (!BassGapless.Init() || !BassGaplessAsio.Init()) { Assert.Fail("Failed to initialize GAPLESS."); } var sourceChannel1 = Bass.CreateStream(@"D:\Source\Prototypes\Resources\01 Botanical Dimensions.flac", 0, 0, BassFlags.Decode | BassFlags.Float); if (sourceChannel1 == 0) { Assert.Fail(string.Format("Failed to create source stream: {0}", Enum.GetName(typeof(Errors), Bass.LastError))); } var sourceChannel2 = Bass.CreateStream(@"D:\Source\Prototypes\Resources\02 Outer Shpongolia.flac", 0, 0, BassFlags.Decode | BassFlags.Float); if (sourceChannel2 == 0) { Assert.Fail(string.Format("Failed to create source stream: {0}", Enum.GetName(typeof(Errors), Bass.LastError))); } var channelInfo = default(ChannelInfo); if (!Bass.ChannelGetInfo(sourceChannel1, out channelInfo)) { Assert.Fail(string.Format("Failed to get channel info: {0}", Enum.GetName(typeof(Errors), Bass.LastError))); } if (!BassGapless.ChannelEnqueue(sourceChannel1)) { Assert.Fail("Failed to add stream to gapless queue."); } if (!BassGapless.ChannelEnqueue(sourceChannel2)) { Assert.Fail("Failed to add stream to gapless queue."); } var sourceChannelCount = default(int); var sourceChannels = BassGapless.GetChannels(out sourceChannelCount); if (sourceChannelCount != 2) { Assert.Fail("Gapless reports unexpected queued channel count."); } if (sourceChannels[0] != sourceChannel1 || sourceChannels[1] != sourceChannel2) { Assert.Fail("Gapless reports unexpected queued channel handles."); } { var ok = true; ok &= BassGaplessAsio.ChannelEnable(false, 0); ok &= BassAsio.ChannelJoin(false, 1, 0); ok &= BassAsio.ChannelSetFormat(false, 0, AsioSampleFormat.Float); ok &= BassAsio.ChannelSetRate(false, 0, channelInfo.Frequency); if (!ok) { Assert.Fail("Failed to configure ASIO."); } } if (!BassAsio.Start()) { Assert.Fail(string.Format("Failed to start ASIO: {0}", Enum.GetName(typeof(Errors), BassAsio.LastError))); } var channelLength = Bass.ChannelGetLength(sourceChannel1); var channelLengthSeconds = Bass.ChannelBytes2Seconds(sourceChannel1, channelLength); Bass.ChannelSetPosition(sourceChannel1, Bass.ChannelSeconds2Bytes(sourceChannel1, channelLengthSeconds - 10)); do { var channelActive1 = Bass.ChannelIsActive(sourceChannel1); var channelActive2 = Bass.ChannelIsActive(sourceChannel2); if (channelActive1 == PlaybackState.Stopped && channelActive2 == PlaybackState.Stopped) { break; } var channelPosition = Bass.ChannelGetPosition(sourceChannel2); var channelPositionSeconds = Bass.ChannelBytes2Seconds(sourceChannel2, channelPosition); if (channelPositionSeconds >= 10) { break; } Thread.Sleep(1000); } while (true); if (BassGapless.ChannelRemove(sourceChannel1)) { Assert.Fail("Queued gapless channel should have been removed."); } if (!BassGapless.ChannelRemove(sourceChannel2)) { Assert.Fail("Failed to remove queued gapless channel."); } BassAsio.Stop(); Bass.StreamFree(sourceChannel1); Bass.StreamFree(sourceChannel2); BassGapless.Free(); BassGaplessAsio.Free(); BassAsio.Free(); Bass.Free(); }
private void Quit_Click(object sender, EventArgs e) { BassAsio.BASS_ASIO_Free(); Close(); Dispose(); }
private void timer1_Tick(object sender, EventArgs e) { // PresentPanel.Visible = false; #region log: poprawne przejscie do timera if (!File.Exists(@"log.txt")) { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string temp = "log file for experiment"; writer.WriteLine(temp); } } try { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string date_time = DateTime.Now.ToString(); string temp = date_time + " poprawnie wejscie do timera"; writer.WriteLine(temp); } } catch { } #endregion BassAsio.BASS_ASIO_Stop(); _hGCFile.Free(); GC.Collect(); #region log: poprawne zatrzymanie odtwarzania dźwięku if (!File.Exists(@"log.txt")) { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string temp = "log file for experiment"; writer.WriteLine(temp); } } try { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string date_time = DateTime.Now.ToString(); string temp = date_time + " poprawnie zakończono odtwarzanie dźwieku"; writer.WriteLine(temp); } } catch { } #endregion player.Pause(); player.Stop(); #region log: poprawne zatrzymanie odtwarzania wideo if (!File.Exists(@"log.txt")) { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string temp = "log file for experiment"; writer.WriteLine(temp); } } try { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string date_time = DateTime.Now.ToString(); string temp = date_time + " poprawnie zakończono odtwarzanie obrazu"; writer.WriteLine(temp); } } catch { } #endregion Visual_Taking_Response(); System.Threading.Thread.Sleep(200); GC.Collect(); timer1.Enabled = false; }
// メソッド 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(CTimer.E種別.MultiMedia); 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); } }
public void przygotowanie_odtwarzania() { //czas odtwarzania probki audio_stoper_length = plik_wejsciowy.get_sample_length(current_sample); #region jesli ma byc odtwarzany dzwiek try { BassAsio.BASS_ASIO_Stop(); BassAsio.BASS_ASIO_Free(); } catch { } //================================================================================= // Kopiowanie całego strumienia audio do pamięci // //otwarcie pliku audio, pobranie jego wielkosci //wczytanie pliku do buforu //zamkniecie pliku //utworzenie uchwytu, ktory zapobiegnie usunieciu pliku //ustawienie czasu odtwarzania //================================================================================= FileStream fs = File.OpenRead(plik_wejsciowy.get_audio_samp(current_sample)); byte[] temp = new byte[44]; fs.Read(temp, 0, 44); long lf = 44 + BitConverter.ToUInt32(temp, 40); length = lf + BitConverter.ToUInt32(temp, 28); audio_buffer = new byte[length]; for (long i = 0; i < length; i++) { audio_buffer[i] = 0; } fs.Position = 0; fs.Read(audio_buffer, 0, (int)lf); fs.Close(); _hGCFile = GCHandle.Alloc(audio_buffer, GCHandleType.Pinned); //================================================================================= // Przygotowanie całego BASS_Asio //================================================================================= Asio_Setup(urzadzenie); #endregion //================================================================================= // Przygotowanie odtwarzacza //================================================================================= // Player_Setup(Application.StartupPath + "\\" + plik_wejsciowy.get_video_samp(current_sample)); Player_Setup(plik_wejsciowy.get_video_samp(current_sample)); //================================================================================= // odtwarzanie //================================================================================= player.Play(); if (!BassAsio.BASS_ASIO_Start(0)) { // BASSError blad = BassAsio.BASS_ASIO_ErrorGetCode(); // MessageBox.Show("błąd odtwarzania: " + blad.ToString()); } #region log: poprawne rozpoczecie odtwarzania sampli if (!File.Exists(@"log.txt")) { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string tmp = "log file for experiment"; writer.WriteLine(tmp); } } try { using (StreamWriter writer = new StreamWriter(@"log.txt", true)) { string date_time = DateTime.Now.ToString(); string tmp = date_time + " poprawnie rozpoczecie odtarzania sampli: \n\t" + plik_wejsciowy.get_video_samp(current_sample) + "\n\t" + plik_wejsciowy.get_audio_samp(current_sample); writer.WriteLine(tmp); } } catch { } #endregion timer1.Interval = audio_stoper_length; timer1.Enabled = true; }
public override void Kill() { BassAsio.BASS_ASIO_Stop(); }
public override void Resume() { BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_PAUSE); }
public override void Pause() { BassAsio.BASS_ASIO_ChannelPause(false, 0); }
private void SetDummyASIOInfo() { DeviceName.Text = String.Format("The device refused to be interrogated by BASSASIO. ({0})", BassAsio.BASS_ASIO_ErrorGetCode().ToString()); Inputs.Text = "N/A"; Outputs.Text = "N/A"; BufferInfo.Text = "N/A"; }