Example #1
0
        private static unsafe void SoundCallbackPlaying(IntPtr hwi, uint uMsg, SoundWrapper dwInstance, uint dwParam1, uint dwParam2)
        {
            if (uMsg == WOM_DONE)
            {
                WAVEHDR *bufptr = (WAVEHDR *)dwParam1;

                short[] data = new short[dwInstance.bufferLengthBytes / 2];
                dwInstance.OnNewDataRequested(data);

                Marshal.Copy(data, 0, bufptr->lpData, (int)(dwInstance.bufferLengthBytes / 2));

                if (!dwInstance.finishing)
                {
                    uint retval, retval2, retval3;

                    lock (dwInstance.locker)
                    {
                        retval  = waveOutUnprepareHeader(dwInstance.waveHandle, ref *bufptr, 32);
                        retval2 = waveOutPrepareHeader(dwInstance.waveHandle, ref *bufptr, 32);
                        retval3 = waveOutWrite(dwInstance.waveHandle, ref *bufptr, 32);
                    }

                    if (retval != 0 || retval2 != 0 || retval3 != 0)
                    {
                        System.Windows.Forms.MessageBox.Show(string.Format("error in WOM_DATA: {0} {1} {2}\n", retval, retval2, retval3));
                    }
                }
            }
        }
Example #2
0
        private static unsafe void SoundCallbackRecording(IntPtr hwi, uint uMsg, SoundWrapper dwInstance, uint dwParam1, uint dwParam2)
        {
            if (uMsg == WIM_DATA)
            {
                WAVEHDR *bufptr = (WAVEHDR *)dwParam1;

                short[] data = new short[dwInstance.bufferLengthBytes / 2];
                Marshal.Copy(bufptr->lpData, data, 0, (int)(bufptr->dwBytesRecorded / 2));

                if (!dwInstance.finishing)
                {
                    uint retval, retval2, retval3;

                    lock (dwInstance.locker)
                    {
                        retval  = waveInUnprepareHeader(dwInstance.waveHandle, ref *bufptr, 32);
                        retval2 = waveInPrepareHeader(dwInstance.waveHandle, ref *bufptr, 32);
                        retval3 = waveInAddBuffer(dwInstance.waveHandle, ref *bufptr, 32);
                    }

                    if (retval != 0 || retval2 != 0 || retval3 != 0)
                    {
                        System.Windows.Forms.MessageBox.Show(string.Format("error in WIM_DATA: {0} {1} {2}\n", retval, retval2, retval3));
                    }
                }

                dwInstance.OnNewDataPresent(data);
            }
        }
Example #3
0
        public void Stop()
        {
            if (waveHandle == IntPtr.Zero)
            {
                return;
            }

            finishing = true;

            lock (locker)
            {
                if (mode == Mode.Record)
                {
                    CheckError(waveInReset(waveHandle));
                }
                else
                {
                    CheckError(waveOutReset(waveHandle));
                }
            }

            for (int i = 0; i < 2; ++i)
            {
                unsafe
                {
                    WAVEHDR *bufptr = (WAVEHDR *)bufferIP[i].ToPointer();

                    if (mode == Mode.Record)
                    {
                        CheckError(waveInUnprepareHeader(waveHandle, ref *bufptr, 32));
                    }
                    else if (mode == Mode.Play)
                    {
                        CheckError(waveOutUnprepareHeader(waveHandle, ref *bufptr, 32));
                    }

                    Marshal.FreeHGlobal(bufptr->lpData);
                    Marshal.FreeHGlobal(bufferIP[i]);
                }
            }

            if (mode == Mode.Record)
            {
                CheckError(waveInClose(waveHandle));
            }
            else if (mode == Mode.Play)
            {
                CheckError(waveOutClose(waveHandle));
            }

            waveHandle = IntPtr.Zero;
            finishing  = false;
        }
Example #4
0
 // este funcion callback se llama cuando el circuito de audio termino de procesar el paquete en el contexto de la funcion Play
 unsafe static void WaveOutDonePlay(IntPtr dev, int uMsg, int dwUser, int dwParam1, int dwParam2)
 {
     if ((uMsg == MM_WOM_DONE))
     {
         IntPtr   PCMBuffer = (IntPtr)dwParam1;
         WAVEHDR *header    = (WAVEHDR *)PCMBuffer;
         // tengo que llamar a esta funcion para liberar el header
         waveOutUnprepareHeader(dev, ref *header, sizeof(WAVEHDR));
         // libero la memoria
         Marshal.FreeHGlobal(PCMBuffer);
     }
 }
 public static extern MMRESULT waveOutUnprepareHeader(IntPtr hWaveOut, WAVEHDR *lpWaveOutHdr, int uSize);
 static extern int waveOutWrite(IntPtr hwo, WAVEHDR *wh, uint cbwh);
 static extern int waveOutUnprepareHeader(IntPtr hwo, WAVEHDR *wh, uint cbwh);
Example #8
0
        public unsafe void Play(float freq, float duration, float vol)
        {
            volumen = vol;
            WAVEFORMATEX Format = new WAVEFORMATEX();

            Format.cbSize          = 0;
            Format.wFormatTag      = WAVE_FORMAT_PCM;
            Format.nChannels       = 1;
            Format.nSamplesPerSec  = SAMPLE_RATE;
            Format.wBitsPerSample  = 16;
            Format.nBlockAlign     = 2;
            Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;
            waveOutOpen(out hWaveOut, WAVE_MAPPER, Format, woDonePlay, (IntPtr)0, CALLBACK_FUNCTION);

            // sintetizo una onda con la frecuencia y duracion dadas
            float kv;
            int   cant_samples = (int)(SAMPLE_RATE * duration / 1000.0);

            // aloco memoria para el header y para los datos pcm pp dichos, todo junto
            PCMBuffer = Marshal.AllocHGlobal(sizeof(WAVEHDR) + sizeof(short) * cant_samples);
            WAVEHDR *header = (WAVEHDR *)PCMBuffer;
            short *  pcm    = (short *)(PCMBuffer + sizeof(WAVEHDR));

            for (int j = 0; j < cant_samples; j++)
            {
                // dice que la conversion es redundante.....las pelotas es redundante... si no lo convertis a doble da siempre cero!!!
                double t  = (double)j / (double)SAMPLE_RATE;    // tiempo transcurrido
                float  s0 = 0.1f;
                float  s1 = 0.95f;
                float  s  = (float)j / (float)cant_samples;
                if (s < s0)
                {
                    kv = s / s0;
                }
                else
                if (s > s1)
                {
                    kv = (1 - s) / (1 - s1);
                }
                else
                {
                    kv = 1;
                }
                double value = Math.Sin(2 * Math.PI * freq * t) + 0.3 * Math.Sin(4 * Math.PI * freq * t);
                value = value * volumen * kv;
                if (value < -1)
                {
                    value = -1;
                }
                else
                if (value > 1)
                {
                    value = 1;
                }
                pcm[j] = (short)(value * 32500.0);
            }


            header->lpData = (IntPtr)pcm;
            header->dwAudioBufferLength = (uint)(sizeof(short) * cant_samples);
            header->dwFlags             = WHDR_BEGINLOOP | WHDR_ENDLOOP;
            header->dwLoops             = 1;

            if (waveOutPrepareHeader(hWaveOut, ref *header, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
            {
                if (waveOutWrite(hWaveOut, ref *header, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
                {
                }
            }
        }
 public static extern MMRESULT waveInAddBuffer(IntPtr hWaveIn, WAVEHDR *pwh, int cbwh);
Example #10
0
        // esta funcion se llama continuamente, pero hay que sincronizar, de tal forma que el circuito
        // de audio nunca se quede sin datos, pero sin llenar el buffer de salida
        // entonces la idea es que cada vez que mando un paqueta sumo en uno la cantidad de bloques enviados
        // y cada vez que el circuito termina de tocarlos me avisa y decremento uno.

        public unsafe void WaveOut()
        {
            int cant_bloques = *(int *)p_cant_bloques;

            if (cant_bloques >= 10)
            {
                return;             // mejor espero
            }
            // Avanzo el tiempo
            long T1;   // address of current frequency

            QueryPerformanceCounter(out T1);
            elapsed_time = (double)(T1 - T0) / (double)F;
            T0           = T1;

            // quiero generar una onda que dure el mismo tiempo que el lap del timer. (que es el dt del timer)
            // y un 10% mas, de tal forma de evitar el clack entre switchs
            // cant samples = SAMPLE_RATE * dt;		(dt ==1 )
            uint cant_samples = (uint)(SAMPLE_RATE * lap * 1.1f);
            uint pcm_size     = cant_samples * sizeof(short);
            // el bloque esta compuesto del header (WAVEHDR) y el pcm data pp dicho
            uint     block_size = (uint)sizeof(WAVEHDR) + pcm_size;
            byte *   p_buff     = ((byte *)AudioBuffer + AudioBufferIndex);
            WAVEHDR *header     = (WAVEHDR *)p_buff;
            short *  pcm        = (short *)(p_buff + sizeof(WAVEHDR));
            short *  wav        = (short *)(PCMBuffer);

            float k_freq = 1.0f;

            for (int j = 0; j < cant_samples; j++)
            {
                float s   = j / cant_samples;
                int   ndx = (int)(index * k_freq) % _cant_samples;
                pcm[j] = (short)((wav[ndx]) * volumen);
                ++index;
            }
            header->lpData = (IntPtr)pcm;
            header->dwAudioBufferLength = pcm_size;
            header->dwFlags             = WHDR_BEGINLOOP | WHDR_ENDLOOP;
            header->dwLoops             = 1;


            // analisis de fourier
            fft.ComplexFFT(pcm, (int)cant_samples, 16384, 1);


            if (waveOutPrepareHeader(hWaveOut, ref *header, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
            {
                if (waveOutWrite(hWaveOut, ref *header, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
                {
                    // incremento el indice dentro el buffer de audio, que se comporta como una lista circular
                    // cuando me quedo sin lugar arranca de nuevo donde seguro que esos paquetes ya fueron procesados
                    AudioBufferIndex += block_size;
                    if (AudioBufferIndex >= AudioBufferSize)
                    {
                        AudioBufferIndex = 0;
                    }
                    (*(int *)p_cant_bloques)++;      // un bloque mas
                }
            }
        }
Example #11
0
 public static extern uint waveInAddBuffer(HWAVEIN hwi, [NativeTypeName("LPWAVEHDR")] WAVEHDR *pwh, uint cbwh);
Example #12
0
 public static extern uint waveInUnprepareHeader(HWAVEIN hwi, [NativeTypeName("LPWAVEHDR")] WAVEHDR *pwh, uint cbwh);
 public static extern MMRESULT waveOutWrite(IntPtr hWaveOut, WAVEHDR *pwh, int cbwh);
Example #14
0
 internal static extern MMRESULT waveInPrepareHeader(IntPtr hWaveIn, WAVEHDR *pwh, int cbwh);
Example #15
0
 internal static extern MMRESULT waveOutPrepareHeader(IntPtr hWaveOut, WAVEHDR *lpWaveOutHdr, int uSize);
Example #16
0
 public static extern uint waveOutWrite(HWAVEOUT hwo, [NativeTypeName("LPWAVEHDR")] WAVEHDR *pwh, uint cbwh);
Example #17
0
 public static extern uint waveOutUnprepareHeader(HWAVEOUT hwo, [NativeTypeName("LPWAVEHDR")] WAVEHDR *pwh, uint cbwh);
Example #18
0
        public void Start(DeviceInfo device)
        {
            if (waveHandle != IntPtr.Zero)
            {
                return;
            }

            var  devByName   = EnumerateDevices().FirstOrDefault(i => i.name == device.name);
            uint deviceIndex = ((uint?)devByName?.index) ?? WAVE_MAPPER;

            WAVEFORMATEX waveFormatEx = new WAVEFORMATEX();

            waveFormatEx.wFormatTag     = WAVE_FORMAT_PCM;
            waveFormatEx.nChannels      = channels;
            waveFormatEx.nSamplesPerSec = sampleRate;
            waveFormatEx.wBitsPerSample = bitsPerSample;
            waveFormatEx.cbSize         = 0;

            waveFormatEx.nBlockAlign     = (ushort)(waveFormatEx.nChannels * waveFormatEx.wBitsPerSample / 8);
            waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;

            if (mode == Mode.Record)
            {
                soundCallbackDelegate = SoundCallbackRecording;
                CheckError(waveInOpen(ref waveHandle, deviceIndex, ref waveFormatEx, soundCallbackDelegate, this, CALLBACK_FUNCTION));
            }
            else if (mode == Mode.Play)
            {
                soundCallbackDelegate = SoundCallbackPlaying;
                CheckError(waveOutOpen(ref waveHandle, deviceIndex, ref waveFormatEx, soundCallbackDelegate, this, CALLBACK_FUNCTION));
            }

            warmup = 2;

            for (int i = 0; i < 2; ++i)
            {
                unsafe
                {
                    bufferIP[i] = Marshal.AllocHGlobal(32); // to prevent GC from deleting

                    WAVEHDR *bufptr = (WAVEHDR *)bufferIP[i].ToPointer();

                    bufptr->lpData         = Marshal.AllocHGlobal((int)bufferLengthBytes);
                    bufptr->dwBufferLength = bufferLengthBytes;
                    bufptr->dwFlags        = 0;

                    short[] data = new short[bufferLengthBytes / 2];
                    Marshal.Copy(data, 0, bufptr->lpData, (int)(bufferLengthBytes / 2));

                    if (mode == Mode.Record)
                    {
                        CheckError(waveInPrepareHeader(waveHandle, ref *bufptr, 32));
                        CheckError(waveInAddBuffer(waveHandle, ref *(WAVEHDR *)bufferIP[i].ToPointer(), 32));
                    }
                    else if (mode == Mode.Play)
                    {
                        CheckError(waveOutPrepareHeader(waveHandle, ref *bufptr, 32));
                        CheckError(waveOutWrite(waveHandle, ref *(WAVEHDR *)bufferIP[i].ToPointer(), 32));
                    }
                }
            }

            if (mode == Mode.Record)
            {
                CheckError(waveInStart(waveHandle));
            }
        }
 public static extern MMRESULT waveInUnprepareHeader(IntPtr hWaveIn, WAVEHDR *pwh, int cbwh);