Générateur de signal basse fréquence temps réel

Soyez le premier à donner votre avis sur cette source.

Vue 18 271 fois - Téléchargée 1 010 fois

Description

Ce programme permet la fabrication en continu et en temps réel d'un signal sinusoîdal, 20 Hz à 20kHz. Changement de fréquence appliqué instantanément.

Source / Exemple :


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

#define BUFFER_SIZE 4096
#define SAMPLERATE 44100 
#define CANAUX 1 // mono
#define OCTETS 2 // 16 bit

double pi = 3.1415926535897932;

PBYTE Buffer;
BOOL flag_out_open = FALSE;

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

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

  static HWAVEOUT hWaveOut;
  static PBYTE pBufferOut1, pBufferOut2, pBufferOut3;
  static PWAVEHDR pWaveHdrOut1, pWaveHdrOut2, pWaveHdrOut3;
  static WAVEFORMATEX waveform;
  static long int i;
  static double j = 0;
  static float angle;
  static unsigned char val;
  static double frequence[19981];
  static char txt[128];

  if (msg == WM_INITDIALOG)
   {
    for(i=0; i<19981; i++)
     {
      sprintf(txt,"%1.1f Hz", 20000.0 - i);
      frequence[i] = 20000.0 - i;
      SendDlgItemMessage(hWnd, IDC_COMBO_frequence , CB_ADDSTRING , 0 , (LPARAM)txt);
     }
    SendDlgItemMessage(hWnd, IDC_COMBO_frequence, CB_SETCURSEL, 19560, 0);
    return 0;
   }

    

  if (msg == MM_WOM_OPEN)
   {
    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));
    return 0;
   }

  if (msg == MM_WOM_DONE)
   {
    if (OCTETS == 1)
     {
      for(i=0; i<BUFFER_SIZE; i++)
       {
        angle = 2 * pi * j * frequence[SendDlgItemMessage(hWnd, IDC_COMBO_frequence, CB_GETCURSEL , 0 , 0)] / SAMPLERATE;
        if (angle > 2 * pi) angle = angle - 2 * pi;
        val = 127 + 127 * sin(angle);
        Buffer[i] = (val & 255);
        j = j + 1;
       }
     }
    if (OCTETS == 2)
     {
      for(i=0; i<(BUFFER_SIZE>>1); i++)
       {
        angle = 2 * pi * j * frequence[SendDlgItemMessage(hWnd, IDC_COMBO_frequence, CB_GETCURSEL , 0 , 0)] / SAMPLERATE;
        if (angle > 2 * pi) angle = angle - 2 * pi;
        val = 32767 * sin(angle);
        Buffer[  2*i] = (char)(val & 255);
        Buffer[1+2*i] = (char)(val >> 8);
        j = j + 1;
       }
     }
    CopyMemory(((PWAVEHDR)lParam)->lpData, Buffer, BUFFER_SIZE);
    waveOutPrepareHeader(hWaveOut, ((PWAVEHDR)lParam), sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, ((PWAVEHDR)lParam), sizeof(WAVEHDR));
    return 0;
   }

  if (msg == WM_COMMAND)
   {
    if (wParam == ID_START)
     {
      if(flag_out_open == TRUE)
       {
        MessageBox(hWnd,"périphérique déjà ouvert","Erreur",0);
        return 0;
       }     

      pWaveHdrOut1 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrOut2 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      pWaveHdrOut3 = (PWAVEHDR) malloc(sizeof(WAVEHDR));
      
      Buffer      = (PBYTE)malloc(BUFFER_SIZE);
      pBufferOut1 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferOut2 = (PBYTE)malloc(BUFFER_SIZE);
      pBufferOut3 = (PBYTE)malloc(BUFFER_SIZE);
    
      if(!pBufferOut1 || !pBufferOut2 || !pBufferOut3)
       {
        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(waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,(DWORD)hWnd,0,CALLBACK_WINDOW))
       {
        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)
{
  DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1),HWND_DESKTOP,DlgProc);
  return 0;
}

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

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

acx01b
Messages postés
281
Date d'inscription
dimanche 7 septembre 2003
Statut
Membre
Dernière intervention
8 juillet 2014
3 -
salut,

il est plus intéressant au niveau performance je pense de calculer les points de la sinusoïde à l'aide des complexes
(a+ib)(c+id) = (ac-bd) + i(ad+bc)

double angle = 2*M_PI/n;

double a = cos(angle);
double b = sin(angle);
double c = 1;
double d[4*n];

int i;
tab[0] = 0;
for (i=1; i < 2*n; i++) {
tmp = a*c-b*d[2*i-2];
tab[2*i] = a*d[2*i-2]+b*c;
}

dans le tableau c tu as alors toute ta période

a+
acx01b
Messages postés
281
Date d'inscription
dimanche 7 septembre 2003
Statut
Membre
Dernière intervention
8 juillet 2014
3 -
dans le tableau d pardon
acx01b
Messages postés
281
Date d'inscription
dimanche 7 septembre 2003
Statut
Membre
Dernière intervention
8 juillet 2014
3 -
troisième essai...


double angle = 2*M_PI/n;

double a = cos(angle);
double b = sin(angle);
double c = 1;
double d[2*n];

int i;
tab[0] = 0;
for (i=0; i < 2*n-1; i++) {
c = a*c-b*d[i];
d[i+1] = a*d[i]+b*c;
}

dans le tableau d tu as alors toute ta période
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Quand la fenêtre est réduite ou restaurée, il y a une courte interruption du processus.
Doit-on utiliser un thread ou un SetPriorityClass ou un EnterCriticalSection ?
Taron31
Messages postés
199
Date d'inscription
vendredi 16 avril 2004
Statut
Membre
Dernière intervention
28 février 2008
-
si tu veux être encore plus performant, tu peux coder en asm inline avec la FPU les calculs des flottants...

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.