protected void UpdatePlaySpeed() { int?speed = this._speed; if (!speed.HasValue) { return; } float offset = (float)Math.Abs(speed.Value) / _PLAY_SPEED_ZOOM_MULIT; var waveInfo = this.WaveInfo; if (waveInfo == null) { throw new WavException("句柄已释放"); } var sampleRate = waveInfo.SampleRate; float playSampleRate; if (speed.Value < 0) { playSampleRate = sampleRate * (1 - offset); } else if (speed.Value == 0) { playSampleRate = sampleRate; } else { playSampleRate = sampleRate * (1 + offset); } WavHelper.ChannelSetSpeed(this._handle, playSampleRate); }
/// <summary> /// 开始录音 /// </summary> /// <param name="freq">录音采样率,默认48000</param> /// <param name="chans">声道数[1-6],默认1</param> /// <param name="period">录音数据输出间隔,单位/毫秒,默认100.最小值5ms,the maximum the maximum is half the BASS_CONFIG_REC_BUFFER setting. /// If the period specified is outside this range, it is automatically capped. The default is 100ms</param> /// <param name="sampleType">采样类型,建议默认值16位</param> public void Start(int freq = 48000, int chans = 1, int period = 100, SampleType sampleType = SampleType.Sample16Bit) { BASSFlag flags = this.SampleTypeToBASSFlag(sampleType); this._recordFlag = true; this._handle = RecordHelper.RecordStart(freq, chans, flags, period, this._recordPro, IntPtr.Zero); WavHelper.ChannelPlay(this._handle, false); }
protected override void FreeBASS() { this._waveInfo = null; base.FreeBASS(); if (base.HandleValid()) { WavHelper.BASS_ChannelRemoveSync(base._handle, this._playEndSyncHandle); } }
/// <summary> /// 播放 /// </summary> public void Play() { if (this.ValidatePPSOperate(SoundPlayerStatus.Playing)) { this._status = SoundPlayerStatus.StartPlaying; WavHelper.ChannelPlay(this._handle, this.Status == SoundPlayerStatus.Stoped); this._status = SoundPlayerStatus.Playing; this.OnPlayStatusChanged(); } }
/// <summary> /// 停止 /// </summary> public void Stop() { if (this.ValidatePPSOperate(SoundPlayerStatus.Stoped)) { this._status = SoundPlayerStatus.Stoping; WavHelper.ChannelStop(this._handle); this._status = SoundPlayerStatus.Stoped; this.OnPlayStatusChanged(); } }
/// <summary> /// 暂停 /// </summary> public void Pause() { if (this.ValidatePPSOperate(SoundPlayerStatus.Paused)) { this._status = SoundPlayerStatus.Pausing; WavHelper.ChannelPause(this._handle); this._status = SoundPlayerStatus.Paused; this.OnPlayStatusChanged(); } }
/// <summary> /// 获取音频文件信息 /// </summary> /// <returns>音频文件信息</returns> public BASS_CHANNELINFO_INTERNAL GetWavInfo() { if (this.HandleValid()) { return(WavHelper.ChannelGetInfo(this._handle)); } else { throw new WavException("未加载音频数据"); } }
/// <summary> /// 声音淡入淡出 /// </summary> /// <param name="volValue">音量目标值</param> /// <param name="duration">持续时间,单位/毫秒</param> public void VoiceSlide(float volValue, int duration) { if (!this.HandleValid()) { return; } //float value = 0.2f; //int duration=2*1000; WavHelper.ChannelSlideAttribute(this._handle, BASSAttribute.BASS_ATTRIB_VOL, volValue, duration); }
/// <summary> /// 获取实时FFT数据,float类型 /// </summary> /// <param name="fftData">FFT数据存放数据</param> /// <returns>获取到的FFT数据长度</returns> public int GetFFTDataFloat(float[] fftData) { if (this.HandleValid()) { return(WavHelper.ChannelGetData(this._handle, fftData, fftData.Length)); } else { throw new ArgumentException("句柄无效"); } }
/// <summary> /// 播放状态改变通知 /// </summary> protected override void OnPlayStatusChanged() { base.OnPlayStatusChanged(); var state = WavHelper.ChannelIsActive(base._handle); if (state != BASSActive.BASS_ACTIVE_PAUSED && state != BASSActive.BASS_ACTIVE_PAUSED_DEVICE && state != BASSActive.BASS_ACTIVE_PLAYING) { this._waveInfo = null; } }
protected virtual void FreeBASS() { try { if (this.HandleValid()) { WavHelper.StreamFree(this._handle); this._handle = WavConstant.NONE_HANDLE; } } catch (Exception ex) { WavLoger.OnRaiseLog(this, ex); } }
/// <summary> /// 构造函数 /// </summary> /// <param name="waveInfo">音频信息</param> /// <param name="bufferCapcity">缓存容量,小于等于0自动计算</param> public StreamSoundPlayer(WaveInfo waveInfo, int bufferCapcity = -1) : base(SoundPlayerType.Stream) { this._waveInfo = waveInfo; int bitByteCount; BASSFlag flags; switch (waveInfo.SampleBit) { case SampleType.Sample8Bit: flags = BASSFlag.BASS_DEFAULT | BASSFlag.BASS_SAMPLE_8BITS; bitByteCount = 1; break; case SampleType.Sample16Bit: flags = BASSFlag.BASS_DEFAULT; bitByteCount = 2; break; case SampleType.Sample32Bit: flags = BASSFlag.BASS_DEFAULT | BASSFlag.BASS_SAMPLE_FLOAT; bitByteCount = 4; break; default: throw new NotImplementedException($"未实现的采样类型:{waveInfo.SampleBit.ToString()}"); } if (bufferCapcity == -1) { bufferCapcity = waveInfo.SampleRate * waveInfo.ChannelCount * bitByteCount * 10;//默认缓存10秒数据 } if (bufferCapcity > 0) { this._buffer = new byte[bufferCapcity]; } this._streamProc = new STREAMPROC(this.StreamProcCallback); base._handle = WavHelper.StreamCreate(waveInfo.SampleRate, waveInfo.ChannelCount, flags, this._streamProc, IntPtr.Zero); //base._device = WavHelper.ChannelGetDevice(base._handle); }
/// <summary> /// 加载音频文件 /// </summary> /// <param name="filePath">音频路径</param> public void LoadWav(string filePath) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException(nameof(filePath), "文件路径不能为空或null"); } if (!File.Exists(filePath)) { throw new FileNotFoundException("音频文件不存在", filePath); } this._fileName = filePath; this.FreeBASS(); base._handle = WavHelper.StreamCreateFile(filePath); this._playEndSyncHandle = WavHelper.ChannelSetSync(this._handle, BASSSync.BASS_SYNC_END, -1, this._playEndNotifyCallback, IntPtr.Zero); //WavHelper.ChannelSetSync(this._handle, BASSSync.BASS_SYNC_MIXTIME, -1, this._playPositionChangedNotifyCallback, IntPtr.Zero); this.SetPlayerAttribute(); }
/// <summary> /// 获取设备数 /// </summary> /// <returns>设备数</returns> public static int GetDeviceCount() { int deviceCount = 0; BASS_DEVICEINFO_INTERNAL info = new BASS_DEVICEINFO_INTERNAL(); for (int i = 0; ; i++) { if (WavHelper.GetDeviceInfo(i, ref info)) { deviceCount++; } else { break; } } return(deviceCount); }
/// <summary> /// 获取解码后的线性short数据 /// </summary> /// <returns>解码后的线性short数据</returns> public static PcmDataInfo GetPcmDataShort(string filePath) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (!File.Exists(filePath)) { throw new FileNotFoundException("源文件不存在", filePath); } int handle = WavHelper.StreamCreateFile(filePath, 0, 0, BASSFlag.BASS_UNICODE | BASSFlag.BASS_STREAM_DECODE); try { long byteLength = WavHelper.ChannelGetLength(handle, BASSMode.BASS_POS_BYTE); double durationSeconds = WavHelper.ChannelBytes2Seconds(handle, byteLength); int shortCount = (int)(byteLength); short[] pcmData = new short[shortCount]; int count = WavHelper.ChannelGetData(handle, pcmData, shortCount); //注:结果数据长度之所以除以2,是因为short=2byte,bass获取数据时必须使用字节长度,否则数据会少一半; //但是使用字节长度获取数据后,后一半数据又全是0,需要截取掉 count = count / 2; short[] pcmDataSrc = pcmData; pcmData = new short[count]; Array.Copy(pcmDataSrc, pcmData, count); BASS_CHANNELINFO_INTERNAL wavInfo = WavHelper.ChannelGetInfo(handle); return(new PcmDataInfo(wavInfo, durationSeconds, pcmData)); } finally { WavHelper.StreamFree(handle); } }
/// <summary> /// 获取解码后的线性byte数据 /// </summary> /// <returns>解码后的线性byte数据</returns> public static PcmDataInfo GetPcmDataByte(string filePath) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (!File.Exists(filePath)) { throw new FileNotFoundException("源文件不存在", filePath); } int handle = WavHelper.StreamCreateFile(filePath, 0, 0, BASSFlag.BASS_UNICODE | BASSFlag.BASS_STREAM_DECODE); try { long byteLength = WavHelper.ChannelGetLength(handle, BASSMode.BASS_POS_BYTE); double durationSeconds = WavHelper.ChannelBytes2Seconds(handle, byteLength); byte[] pcmData = new byte[byteLength]; int count = WavHelper.ChannelGetData(handle, pcmData, (int)byteLength); if (count != byteLength) { WavLoger.OnRaiseLog(filePath, $"获取到文件长度:{byteLength},读取到数据长度:{count},二者不一致,根据实际读取进行拷贝"); byte[] pcmDataSrc = pcmData; pcmData = new byte[count]; Array.Copy(pcmDataSrc, pcmData, pcmData.Length); } BASS_CHANNELINFO_INTERNAL wavInfo = WavHelper.ChannelGetInfo(handle); return(new PcmDataInfo(wavInfo, durationSeconds, pcmData)); } finally { WavHelper.StreamFree(handle); } }
/// <summary> /// 初始化声音输出设备 /// </summary> /// <param name="device"> -1 = default device, 0 = no sound, 1 = first real output device. BASS_GetDeviceInfo can be used to enumerate the available devices. </param> /// <param name="freq">输出率</param> /// <param name="flags">A combination of these flags</param> public static void InitDevice(int device, int freq, BASSInit flags) { WavHelper.Init(device, freq, flags); }
protected void UpdateVolume() { WavHelper.ChannelSetVolume(this._handle, this._volume.Value); }
protected void UpdateBalance() { WavHelper.ChannelSetAttribute(this._handle, BASSAttribute.BASS_ATTRIB_PAN, this._balance.Value); }
/// <summary> /// Frees all resources used by the output device, including all its samples, streams and MOD musics /// </summary> public static void Free() { WavHelper.Free(); }