Moteur audio temps reel

Description

Fonctionnement: le signal en entrée ligne du PC sort directement à la sortie avec un léger retard du au temps de rotation de tous les buffers.

Ce code permet d'effectuer du traitement de signal en temps réel en modifiant le contenu du buffer (Buffer)

Source / Exemple :


#include <windows.h>
#include "stdafx.h"
#include "resource.h"
#include <mmsystem.h>
#include <malloc.h>
#include <stdio.h>
#include <commctrl.h>

#define BUFFER_SIZE 16384
#define SAMPLERATE 44100
#define CANAUX 2
#define OCTETS 2

HWND DlgMain;
PBYTE Buffer;
HWAVEIN hWaveIn;
HWAVEOUT hWaveOut;
PBYTE pBufferIn1, pBufferIn2, pBufferIn3, pBufferOut1, pBufferOut2, pBufferOut3;
PWAVEHDR pWaveHdrIn1, pWaveHdrIn2, pWaveHdrIn3, pWaveHdrOut1, pWaveHdrOut2, pWaveHdrOut3;
WAVEFORMATEX waveform;
BOOL flag_in_open = FALSE;
BOOL flag_out_open = FALSE;

HANDLE WorkerThreadHandleIn;
DWORD WorkerThreadIdIn;
HANDLE WorkerThreadHandleOut;
DWORD WorkerThreadIdOut;

//****************************************************************************

DWORD WINAPI WorkerThreadProcIn (void *Arg)
{
  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
  MSG Msg;

  while (GetMessage (&Msg, NULL, 0, 0) == TRUE)
   {
    switch (Msg.message)
     {
      case MM_WIM_OPEN:
       {
        MessageBox(DlgMain,"In open","RTA",MB_OK);
        flag_in_open = TRUE;
        waveInAddBuffer(hWaveIn,pWaveHdrIn1,sizeof(WAVEHDR));
        waveInAddBuffer(hWaveIn,pWaveHdrIn2,sizeof(WAVEHDR));
        waveInAddBuffer(hWaveIn,pWaveHdrIn3,sizeof(WAVEHDR));
        waveInStart(hWaveIn);  
        break;
       }

      case MM_WIM_DATA:
       {
        WAVEHDR *Hdr = (WAVEHDR *)Msg.lParam;
        CopyMemory(Buffer,Hdr->lpData,BUFFER_SIZE);
        waveInAddBuffer (hWaveIn, Hdr, sizeof (*Hdr));
        break;
       }
     }
   }
  return 0; 
}

//****************************************************************************

DWORD WINAPI WorkerThreadProcOut (void *Arg)
{
  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
  MSG Msg;

  while (GetMessage (&Msg, NULL, 0, 0) == TRUE)
   {
    switch (Msg.message)
     {
      case MM_WOM_OPEN:
       {
        MessageBox(DlgMain,"Out open","RTA",MB_OK);
        flag_out_open = TRUE;
        waveOutPrepareHeader(hWaveOut,pWaveHdrOut1,sizeof(WAVEHDR));
        waveOutWrite(hWaveOut,pWaveHdrOut1,sizeof(WAVEHDR));
        waveOutPrepareHeader(hWaveOut,pWaveHdrOut2,sizeof(WAVEHDR));
        waveOutWrite(hWaveOut,pWaveHdrOut2,sizeof(WAVEHDR));
        waveOutPrepareHeader(hWaveOut,pWaveHdrOut3,sizeof(WAVEHDR));
        waveOutWrite(hWaveOut,pWaveHdrOut3,sizeof(WAVEHDR));
        break;
       }

      case MM_WOM_DONE:
       {
        WAVEHDR *Hdr = (WAVEHDR *)Msg.lParam;
        waveOutPrepareHeader (hWaveOut, Hdr, sizeof (*Hdr));
        waveOutWrite (hWaveOut, Hdr, sizeof (*Hdr));
        CopyMemory(Hdr->lpData,Buffer,BUFFER_SIZE);
        break;
       }
     }
   }
  return 0; 
}

//****************************************************************************

BOOL CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{  

  static int volume_general;

  if (msg == WM_INITDIALOG)
   {
    DlgMain = hWnd;
    return 0;
   }

  if (msg == WM_COMMAND)
   {
    if (wParam == ID_START)
     {
      if(flag_in_open == TRUE)
       {
        MessageBox(hWnd,"périphérique déjà ouvert","Erreur",0);
        return 0;
       }
       
      WorkerThreadHandleIn = CreateThread (NULL, 0, WorkerThreadProcIn, NULL, 0, &WorkerThreadIdIn );
      WorkerThreadHandleOut = CreateThread (NULL, 0, WorkerThreadProcOut, NULL, 0, &WorkerThreadIdOut );
      pWaveHdrIn1 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrIn2 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrIn3 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrOut1 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrOut2 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrOut3 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      
      Buffer   = (PBYTE)malloc(BUFFER_SIZE);
      pBufferIn1 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferIn2 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferIn3 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferOut1 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferOut2 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferOut3 = (PBYTE)malloc(BUFFER_SIZE);
    
      if(!pBufferIn1 || !pBufferIn2 || !pBufferIn3 || !pBufferOut1 || !pBufferOut2 || !pBufferOut3)
       {
        if(pBufferIn1) free (pBufferIn1);
        if(pBufferIn2) free (pBufferIn2);
        if(pBufferIn3) free (pBufferIn3);
        if(pBufferOut1) free (pBufferOut1);
        if(pBufferOut2) free (pBufferOut2);
        if(pBufferOut3) free (pBufferOut3);
        MessageBox(hWnd,"Erreur d'allocation de mémoire","Erreur",0);
        return TRUE;
       }     
    
      waveform.nChannels = CANAUX; // 1 pour mono 2 pour stereo
      waveform.wBitsPerSample = 8 * OCTETS; // 8 ou 16 bit
      waveform.nAvgBytesPerSec = SAMPLERATE * waveform.nChannels * waveform.wBitsPerSample/8; // nombre d'octets par seconde
      waveform.wFormatTag = 1; // 1 pour PCM
      waveform.nSamplesPerSec = SAMPLERATE; // frequence d'echantillonnage
      waveform.nBlockAlign = 1;
      waveform.cbSize = 0;

      if(waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)WorkerThreadIdIn,0,CALLBACK_THREAD))
       {
        free(pBufferIn1);
        free(pBufferIn2);
        free(pBufferIn3);
        MessageBox(hWnd,"ouverture du périphérique d'entrée impossible","WARNING",MB_OK);
        return 0;
       }

      pWaveHdrIn1->lpData          = (LPSTR)pBufferIn1;
      pWaveHdrIn1->dwBufferLength  = BUFFER_SIZE;
      pWaveHdrIn1->dwBytesRecorded = 0;
      pWaveHdrIn1->dwUser          = 0;
      pWaveHdrIn1->dwFlags         = 0;
      pWaveHdrIn1->dwLoops         = 0;
      pWaveHdrIn1->lpNext          = NULL;
      pWaveHdrIn1->reserved        = 0;    
      waveInPrepareHeader(hWaveIn,pWaveHdrIn1,sizeof(WAVEHDR));
    
      pWaveHdrIn2->lpData          = (LPSTR)pBufferIn2;
      pWaveHdrIn2->dwBufferLength  = BUFFER_SIZE;
      pWaveHdrIn2->dwBytesRecorded = 0;
      pWaveHdrIn2->dwUser          = 0;
      pWaveHdrIn2->dwFlags         = 0;
      pWaveHdrIn2->dwLoops         = 0;
      pWaveHdrIn2->lpNext          = NULL;
      pWaveHdrIn2->reserved        = 0;    
      waveInPrepareHeader(hWaveIn,pWaveHdrIn2,sizeof(WAVEHDR));

      pWaveHdrIn3->lpData          = (LPSTR)pBufferIn3;
      pWaveHdrIn3->dwBufferLength  = BUFFER_SIZE;
      pWaveHdrIn3->dwBytesRecorded = 0;
      pWaveHdrIn3->dwUser          = 0;
      pWaveHdrIn3->dwFlags         = 0;
      pWaveHdrIn3->dwLoops         = 0;
      pWaveHdrIn3->lpNext          = NULL;
      pWaveHdrIn3->reserved        = 0;    
      waveInPrepareHeader(hWaveIn,pWaveHdrIn3,sizeof(WAVEHDR));      

      if(waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,(DWORD)WorkerThreadIdOut,0,CALLBACK_THREAD))
       {
        free(pBufferOut1);
        free(pBufferOut2);
        free(pBufferOut3);
        MessageBox(hWnd,"ouverture du périphérique de sortie impossible","WARNING",MB_OK);
        return 0;
       }    

      pWaveHdrOut1->lpData = (LPSTR)pBufferOut1;
      pWaveHdrOut1->dwBufferLength = BUFFER_SIZE;
      pWaveHdrOut1->dwBytesRecorded = 0;
      pWaveHdrOut1->dwUser = 0;
      pWaveHdrOut1->dwFlags = 0;
      pWaveHdrOut1->dwLoops = 0;
      pWaveHdrOut1->lpNext = NULL;
      pWaveHdrOut1->reserved = 0;    
      waveOutPrepareHeader(hWaveOut,pWaveHdrOut1,sizeof(WAVEHDR));
    
      pWaveHdrOut2->lpData = (LPSTR)pBufferOut2;
      pWaveHdrOut2->dwBufferLength = BUFFER_SIZE;
      pWaveHdrOut2->dwBytesRecorded = 0;
      pWaveHdrOut2->dwUser = 0;
      pWaveHdrOut2->dwFlags = 0;
      pWaveHdrOut2->dwLoops = 0;
      pWaveHdrOut2->lpNext = NULL;
      pWaveHdrOut2->reserved = 0;    
      waveOutPrepareHeader(hWaveOut,pWaveHdrOut2,sizeof(WAVEHDR));
    
      pWaveHdrOut3->lpData =(LPSTR)pBufferOut3;
      pWaveHdrOut3->dwBufferLength =BUFFER_SIZE;
      pWaveHdrOut3->dwBytesRecorded =0;
      pWaveHdrOut3->dwUser =0;
      pWaveHdrOut3->dwFlags =0;
      pWaveHdrOut3->dwLoops =0;
      pWaveHdrOut3->lpNext =NULL;
      pWaveHdrOut3->reserved =0;    
      waveOutPrepareHeader(hWaveOut,pWaveHdrOut3,sizeof(WAVEHDR));      

      return 0;
     }

    if (wParam == IDCANCEL)
     {
      if(MessageBox(hWnd, "Voulez-vous vraiment arrêter l'application en cours ?", "Real Time Audio",MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2) == IDNO)
       {
        return TRUE;
       }
      EndDialog(hWnd, 0);
      return 0;
     }
   }

  return 0;
}

//****************************************************************************
 
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  InitCommonControls();
  DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1),HWND_DESKTOP,DlgProc);
  return 0;
}

//****************************************************************************

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.