//const int SndOutPacketSize = 512; //short[] Buffer = new short[2 * 1024]; // Frame = 2 * sizeof(ushort) // Period = is the number of frames in between each hardware interrupt. The poll() will return once a period. // PeriodsPerBuffer public AudioAlsaImpl() { if (_playbackHandle != IntPtr.Zero) { return; } try { fixed(IntPtr *playbackHandlePtr = &_playbackHandle) fixed(IntPtr * hwParamsPtr = &_hwParams) { var rate = SampleRate; //int period_time = (SndOutPacketSize * 1000) / (SampleRate / 1000); //int buffer_time = period_time * NumBuffers; Assert("snd_pcm_open", Alsa.snd_pcm_open(playbackHandlePtr, Device, Alsa.snd_pcm_stream_t.SND_PCM_LB_OPEN_PLAYBACK, 0)); Assert("snd_pcm_hw_params_malloc", Alsa.snd_pcm_hw_params_malloc(hwParamsPtr)); Assert("snd_pcm_hw_params_any", Alsa.snd_pcm_hw_params_any(_playbackHandle, _hwParams)); Assert("snd_pcm_hw_params_set_access", Alsa.snd_pcm_hw_params_set_access(_playbackHandle, _hwParams, Alsa.snd_pcm_access.SND_PCM_ACCESS_RW_INTERLEAVED)); Assert("snd_pcm_hw_params_set_format", Alsa.snd_pcm_hw_params_set_format(_playbackHandle, _hwParams, Alsa.snd_pcm_format.SND_PCM_FORMAT_S16_LE)); Assert("snd_pcm_hw_params_set_rate_near", Alsa.snd_pcm_hw_params_set_rate_near(_playbackHandle, _hwParams, &rate, null)); //Assert("snd_pcm_hw_params_set_buffer_time_near", Alsa.snd_pcm_hw_params_set_buffer_time_near(playback_handle, hw_params, &buffer_time, null)); //Assert("snd_pcm_hw_params_set_period_time_near", Alsa.snd_pcm_hw_params_set_period_time_near(playback_handle, hw_params, &period_time, null)); Assert("snd_pcm_hw_params_set_channels", Alsa.snd_pcm_hw_params_set_channels(_playbackHandle, _hwParams, Channels)); Assert("snd_pcm_hw_params_set_periods", Alsa.snd_pcm_hw_params_set_periods(_playbackHandle, _hwParams, Periods, 0)); Assert("snd_pcm_hw_params_set_period_size", Alsa.snd_pcm_hw_params_set_period_size(_playbackHandle, _hwParams, Periodsize, null)); Assert("snd_pcm_hw_params_set_buffer_size", Alsa.snd_pcm_hw_params_set_buffer_size(_playbackHandle, _hwParams, 4 * Periodsize)); Assert("snd_pcm_hw_params", Alsa.snd_pcm_hw_params(_playbackHandle, _hwParams)); Assert("snd_pcm_hw_params_free", Alsa.snd_pcm_hw_params_free(_hwParams)); } } catch (Exception exception) { Console.Error.WriteLine(exception); } //available_start = Alsa.snd_pcm_avail_update(playback_handle); }
//public int available_start; public override void Update(Action <short[]> readStream) { readStream(Buffer); fixed(short *bufferPtr = &Buffer[0]) { if (Alsa.snd_pcm_state(_playbackHandle) == Alsa._snd_pcm_state.SND_PCM_STATE_XRUN) { Alsa.snd_pcm_prepare(_playbackHandle); } Alsa.snd_pcm_writei(_playbackHandle, bufferPtr, Buffer.Length / Channels); } }