ALSA P/Invoke class
예제 #1
0
        //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);
        }
예제 #2
0
        //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);
            }
        }