Moteur audio temps reel avec gestion du volume

Description

Permet de faire passer par un buffer l'entrée ligne et l'envoyer à la sortie carte son en réglant le volume.
Suite du développement: equalizer, analyse de spectre

Source / Exemple :

// base.cpp

#include "stdafx.h"
#include "base.h"

BOOL OpenedIn = FALSE;
HANDLE recordDone;
HWAVEIN hWaveIn;
DWORD threadidIn;
HANDLE RecordHandle;
PWAVEHDR pWaveHeaderIn[NB_BUFFER];

BOOL OpenedOut = FALSE;
HANDLE playDone;
HWAVEOUT hWaveOut;
DWORD threadidOut;
HANDLE PlayHandle;
PWAVEHDR pWaveHeaderOut[NB_BUFFER];

short Buffer[TAILLE_BLOC * CANAUX];

HWND DlgMain;

CRITICAL_SECTION CriticalSection;
int volume_general;        // 0 a 1000

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

void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
  if (uMsg == WIM_OPEN)
   {
    MessageBox(DlgMain,"WIM_OPEN","RTA",MB_OK);
    OpenedIn = TRUE;
   }

  if (uMsg == WIM_CLOSE)
   {
    MessageBox(DlgMain,"WIM_CLOSE","RTA",MB_OK);
   }

  if (uMsg == WIM_DATA) 
   {    
    SetEvent(recordDone);    
   }
}

//****************************************************************************
// 01 WHDR_DONE      indique que c'est fini avec ce buffer.
// 02 WHDR_PREPARED  indique que le buffer a ete prepare (waveInPrepareHeader ou waveOutPrepareHeader)
// 04 WHDR_BEGINLOOP indique que ce buffer est le premier dans une boucle, drapeau utilisé seulement en sortie.
// 08 WHDR_ENDLOOP   indique que ce buffer est le dernier dans une boucle. Ce drapeau est utilisé seulement en sortie.
// 10 WHDR_INQUEUE   indique que le buffer est mis en queue pour la sortie.
//****************************************************************************

DWORD WINAPI InThreadProc(LPVOID lpParam)
{  
  int wbi=0;

__1: WaitForSingleObject(recordDone, INFINITE);  
     if (pWaveHeaderIn[wbi]->dwFlags & WHDR_DONE)
      {
       EnterCriticalSection(&CriticalSection);    
       copier_buffer(Buffer, (short *)pWaveHeaderIn[wbi]->lpData, TAILLE_BLOC * CANAUX); // sauvegarder bloc recu
       waveInUnprepareHeader(hWaveIn, pWaveHeaderIn[wbi], sizeof(WAVEHDR));
       pWaveHeaderIn[wbi]->dwFlags = 0;
       waveInPrepareHeader(hWaveIn, pWaveHeaderIn[wbi], sizeof(WAVEHDR));
       waveInAddBuffer(hWaveIn, pWaveHeaderIn[wbi], sizeof(WAVEHDR));

       __asm // modulo
        {
         mov eax, wbi
         mov ebx, NB_BUFFER
         inc eax
         cmp eax, ebx
         jb fin1
         xor eax, eax
   fin1: mov wbi, eax
        }      
       LeaveCriticalSection(&CriticalSection );
      }

     __asm
      {
       jmp __1
      }

  waveInReset(hWaveIn);
  waveInClose(hWaveIn);
  MessageBox(DlgMain,"FIN","RTA",MB_OK);
  OpenedIn = FALSE;
  return 0;
}

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

void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
  if (uMsg == WOM_OPEN)
   {
    MessageBox(DlgMain,"WOM_OPEN","RTA",MB_OK);
    OpenedOut = TRUE;
   }

  if (uMsg == WOM_CLOSE)
   {
    MessageBox(DlgMain,"WOM_CLOSE","RTA",MB_OK);
   }

  if (uMsg == WOM_DONE) 
   {
    SetEvent(playDone);    
   }
}

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

DWORD WINAPI OutThreadProc(LPVOID lpParam)
{  
  int wbo=0;

__1:WaitForSingleObject(playDone, INFINITE);    

    if (pWaveHeaderOut[wbo]->dwFlags & WHDR_DONE)
     {      
      waveOutUnprepareHeader(hWaveOut, pWaveHeaderOut[wbo], sizeof(WAVEHDR));
      pWaveHeaderOut[wbo]->dwFlags = 0;
      
      regler_volume(Buffer, volume_general, 1000.0, TAILLE_BLOC * CANAUX); // appliquer le volume avant de l'envoyer
      copier_buffer((short *)pWaveHeaderOut[wbo]->lpData, Buffer, TAILLE_BLOC * CANAUX); // reprendre bloc recu
      waveOutPrepareHeader(hWaveOut, pWaveHeaderOut[wbo], sizeof(WAVEHDR));
      waveOutWrite(hWaveOut, pWaveHeaderOut[wbo], sizeof(WAVEHDR));

      __asm
       {
        mov eax, wbo
        mov ebx, NB_BUFFER
        inc eax
        cmp eax, ebx
        jb  fin1
        xor eax, eax
  fin1: mov wbo, eax
       }

     }

__asm
    {
     jmp __1
    }





  return 0;
}

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

int OuvrirPeripheriques()
{
  int i;
  WAVEFORMATEX WaveFormat;
  
  WaveFormat.nChannels = CANAUX; // 1 pour mono 2 pour stereo
  WaveFormat.wBitsPerSample = 16; // 16 bit
  WaveFormat.nAvgBytesPerSec = SAMPLERATE * WaveFormat.nChannels * WaveFormat.wBitsPerSample/8; // nombre d'octets par seconde
  WaveFormat.wFormatTag = 1; // 1 pour PCM
  WaveFormat.nSamplesPerSec = SAMPLERATE; // frequence d'echantillonnage
  WaveFormat.nBlockAlign = 1;
  WaveFormat.cbSize = 0;

  for(i=0; i<NB_BUFFER; i++)
   {
    pWaveHeaderIn[i] = (PWAVEHDR) malloc(sizeof(WAVEHDR));
   }
  
  InitializeCriticalSection(&CriticalSection);

  if (waveInOpen(&hWaveIn, WAVE_MAPPER, &WaveFormat, (DWORD)waveInProc, (DWORD)&CriticalSection, CALLBACK_FUNCTION))
   {
    MessageBox(DlgMain,"Ouverture périphérique d'entrée impossible","RTA",MB_OK);
    return 0;
   }

  for(i=0; i<NB_BUFFER; i++)
   {
    pWaveHeaderIn[i]->lpData          = (LPSTR) malloc(BUFFER_SIZE); // reserve des octets et non des short
    pWaveHeaderIn[i]->dwBufferLength  = BUFFER_SIZE;
    pWaveHeaderIn[i]->dwBytesRecorded = 0;
    pWaveHeaderIn[i]->dwUser          = 0;
    pWaveHeaderIn[i]->dwFlags         = 0;
    pWaveHeaderIn[i]->dwLoops         = 0;
    pWaveHeaderIn[i]->lpNext          = NULL;
    pWaveHeaderIn[i]->reserved        = 0;
   }

  for(i=0; i<NB_BUFFER; i++)
   {
    if (waveInPrepareHeader(hWaveIn, pWaveHeaderIn[i], sizeof(WAVEHDR)))
     {
      MessageBox(DlgMain,"Erreur waveInPrepareHeader","RTA",MB_OK);
      return 0;
     }
   }

  for(i=0; i<NB_BUFFER; i++)
   {
    if (waveInAddBuffer(hWaveIn, pWaveHeaderIn[i], sizeof(WAVEHDR)))
     {
      MessageBox(DlgMain,"Erreur AddBuffer","RTA",MB_OK);
      return 0;
     }
   }

  ResetEvent(recordDone);

  if (waveInStart(hWaveIn))
   {
    waveInClose(hWaveIn);
   }



//****
  for(i=0; i<NB_BUFFER; i++)
   {
    pWaveHeaderOut[i] = (PWAVEHDR) malloc(sizeof(WAVEHDR));
   }

  if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &WaveFormat, (DWORD)waveOutProc, 0L, CALLBACK_FUNCTION))
   {
    MessageBox(DlgMain,"Ouverture périphérique de sortie impossible","RTA",MB_OK);
    return 0;
   }

  for(i=0; i<NB_BUFFER; i++)
   {
    pWaveHeaderOut[i]->lpData          = (LPSTR) malloc(BUFFER_SIZE); // reserve des octets et non des short
    pWaveHeaderOut[i]->dwBufferLength  = BUFFER_SIZE;
    pWaveHeaderOut[i]->dwBytesRecorded = 0;
    pWaveHeaderOut[i]->dwUser          = 0;
    pWaveHeaderOut[i]->dwFlags         = 0;
    pWaveHeaderOut[i]->dwLoops         = 0;
    pWaveHeaderOut[i]->lpNext          = NULL;
    pWaveHeaderOut[i]->reserved        = 0;
   }

  for(i=0; i<NB_BUFFER; i++)
   {
    if (waveOutPrepareHeader(hWaveOut, pWaveHeaderOut[i], sizeof(WAVEHDR)))
     {
      MessageBox(DlgMain,"Erreur PrepareHeader","RTA",MB_OK);
      return 0;
     }
   }

  for(i=0; i<NB_BUFFER; i++)
   {
    if (waveOutWrite(hWaveOut, pWaveHeaderOut[i], sizeof(WAVEHDR)))
     {
      MessageBox(DlgMain,"Erreur OutWrite","RTA",MB_OK);
      return 0;
     }
   }
  ResetEvent(playDone);
//*******


  return 0;
}

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

BOOL CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  if (msg == WM_INITDIALOG)
   {
    DlgMain = hWnd;
    
    char str[128];

    SendDlgItemMessage(hWnd,IDC_SLIDER_VOLUME,TBM_SETRANGEMAX,0,1000);
    SendDlgItemMessage(hWnd,IDC_SLIDER_VOLUME,TBM_SETRANGEMIN,0,0);
    SendDlgItemMessage(hWnd,IDC_SLIDER_VOLUME,TBM_SETPOS,1,0); // volume general a fond
    volume_general = 1000-SendDlgItemMessage(hWnd,IDC_SLIDER_VOLUME,TBM_GETPOS,0,0);
    sprintf(str,"volume: %1.1f dB",20*log10(volume_general/1000));
    SetDlgItemText(hWnd,IDC_STATIC_VOLUME,str);

    return 0;
   }




  if (msg == WM_VSCROLL)
   {
    char str[128];

    volume_general = 1000-SendDlgItemMessage(hWnd,IDC_SLIDER_VOLUME,TBM_GETPOS,0,0);    
    if (volume_general == 0)
     {
      sprintf(str,"volume: -oo");
      SetDlgItemText(hWnd,IDC_STATIC_VOLUME,str);
      return 0;
     }
    sprintf(str,"volume: %1.1f dB", 20*log10(volume_general/1000.0));
    SetDlgItemText(hWnd,IDC_STATIC_VOLUME,str);
    return 0;
   }
   
   
   
     
  if (msg == WM_COMMAND)
   {
    if (wParam == IDC_START)
     {
      if(OpenedIn == TRUE)
       {      
        MessageBox(DlgMain,"Déjà ouvert","RTA",MB_OK);
        return 0;
       }
      recordDone = CreateEvent(0, FALSE, FALSE, 0);
      ResetEvent(recordDone);
      RecordHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InThreadProc, NULL, 0, &threadidIn);

      playDone = CreateEvent(0, FALSE, FALSE, 0);
      ResetEvent(playDone);
      PlayHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) OutThreadProc, NULL, 0, &threadidOut);

      OuvrirPeripheriques();      
      return 0;
     }
  
    if (wParam == IDCANCEL)
     {
      EndDialog(hWnd, 0);
      return 0;
     }
   }




  return 0;
}

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

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  HANDLE hMutex;
  hMutex = CreateMutex (NULL,FALSE, "RTA");
  if (GetLastError() == ERROR_ALREADY_EXISTS)
   {
    MessageBox(NULL,"Cette application est déjà présente en mémoire !","WARNING",MB_OK|MB_ICONEXCLAMATION);
    return 0;
   }

  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.