Moteur audio temps reel avec gestion du volume

Soyez le premier à donner votre avis sur cette source.

Vue 8 622 fois - Téléchargée 755 fois

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

Ajouter un commentaire

Commentaires

Phenixar
Messages postés
9
Date d'inscription
mardi 18 décembre 2001
Statut
Membre
Dernière intervention
27 avril 2007
-
Salut,
je viens de voir ta nouvelle source pour le son.
mais j ai encore un soucis :p ... on ne peux pas choisir l'entrée ni la sortie
dans les 2 cas on se base sur ceux selectionnée par default dans windows
Je ne vois pas comment faire pour choisir une entrée bien precise ainsi qu'une sortie.
Si tu as un conseil n'esite pas.
merci.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Du coup naked ca marche sans problème aussi bien avec VC6 et Visual express c++ 2005
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
ah bien entendu, excuse mais c'est l'habitude qui fait croire évidentes des choses qui ne le sont pas forcément.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Merci BruNews,

Petite précision quand même quant à l'utilisation de naked.

dans le fichier .h de déclaration de fonction il faut mettre:

int __fastcall copier_buffer(void * , void * , int);

et dans le fichier .cpp il faut mettre:

__declspec(naked) int __fastcall copier_buffer(void * dest, void * src, int taille)
{
__asm
{
...
...
}
}
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
Hors EAX, ECX et EDX qui sont considérés comme "écrasés", tous les registres sont à restaurer en sortie de fonction.

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.