Utiliser Fmod pour acquérir des données sonores

Utiliser Fmod pour acquérir des données sonores - C++ - Programmation

Marsh Posté le 24-05-2006 à 13:35:47    

Bonjour à tous,
je travaille sur un projet consistant à analyser en temps réel un flux audio en provenance de l'entrée micro de la carte son afin de détecter des séquences de notes et ainsi déclencher en temps réel des séquences MIDI.
 
J'utilise pour cela la librairie FMOD, mais j'avoue etre un peu perdu concernant son utilisation et surtout le contenu des données.
Je m'explique : J'arrive a enregistrer des données en provenance de l'entrée micro, mais c'est au niveau du découpage que je sèche ... En effet, mon collègue chargé de l'analyse sonore me demande de lui donner un buffer contenant 0.1ms de son au maximum (longueur d'une note sur un tempo de 200 je crois). Ma question est donc, comment découper le buffer de 1 seconde en temps réel en portions de 0.1ms pour analyse.
En vous remerciant pour vos suggestions,
 
ci joint le code :

Code :
  1. // Base from Record.cpp and Brett copie_Sample_Micro_vers_ring_buffer_micro() function
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #if defined(WIN32) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
  6. #include <conio.h>
  7. #include <windows.h>
  8. #define __PACKED /*dummy*/
  9. #else
  10. #include "FMOD/wincompat.h"
  11. #include <string.h>
  12. #define __PACKED __attribute__((packed)) /* gcc packed */
  13. #endif
  14. #include "FMOD/fmod.h"
  15. #include "FMOD/fmod_errors.h" /* optional */
  16. // definir un buffer de 0.1ms -> impossible, solution : buffer 1s dont on découpe les parties
  17. // successives ?
  18. #define PI 3.141517
  19. #define RECORDRATE 44100
  20. #define RECORDLEN (RECORDRATE * 10) /* 1 seconds at RECORDRATE khz */
  21. #define OUTPUTRATE 44100
  22. int BufferSize=4096*3;
  23. int Frequency=44100;
  24. signed short MICRO_INPUT=0;
  25. FSOUND_SAMPLE *samp1;
  26. FSOUND_STREAM *stream;
  27. int mylength_bytes=44100*400;
  28. signed short mybuffer[44100*400+10];
  29. unsigned int myoffset_bytes=0;
  30. signed char F_CALLBACKAPI instrument_callback(FSOUND_STREAM *stream, void *buff, int len, void *param);
  31. int copie_Sample_Micro_vers_ring_buffer_micro();
  32. //DEBUT DU MAIN
  33. int main(int argc, char *argv[])
  34. {
  35.     signed char key;
  36.     int driver, i, channel, originalfreq;
  37.     if (FSOUND_GetVersion() < FMOD_VERSION)
  38.     {
  39.        printf("Error : You are using the wrong DLL version! You should be using FMOD %.02f\n", FMOD_VERSION);
  40.        return 0;
  41.     }
  42.     /*
  43.     SELECT OUTPUT METHOD
  44.     */
  45.     printf("---------------------------------------------------------\n" );
  46.     printf("Output Type\n" );
  47.     printf("---------------------------------------------------------\n" );
  48.     #if defined(WIN32) || defined(_WIN64) || defined(__CYGWIN32__) || defined(__WATCOMC__)
  49.     printf("1 - Direct Sound\n" );
  50.     printf("2 - Windows Multimedia Waveout\n" );
  51.     printf("3 - NoSound\n" );
  52.     #elif defined(__linux__)
  53.     printf("1 - OSS - Open Sound System\n" );
  54.     printf("2 - ESD - Elightment Sound Daemon\n" );
  55.     printf("3 - ALSA 0.9 - Advanced Linux Sound Architecture\n" );
  56.     #endif
  57.     printf("---------------------------------------------------------\n" ); /* print driver names */
  58.     printf("Press a corresponding number or ESC to quit\n" );
  59.    
  60.     do
  61.     {
  62.       key = getch();
  63.     }
  64.     while (key != 27 && key < '1' && key > '4');
  65.    
  66.     switch (key)
  67.     {
  68.         #if defined(WIN32) || defined(_WIN64) || defined(__CYGWIN32__) || defined(__WATCOMC__)
  69.         case '1' : FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
  70.         break;
  71.         case '2' : FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
  72.         break;
  73.         case '3' : FSOUND_SetOutput(FSOUND_OUTPUT_NOSOUND);
  74.         break;
  75.         #elif defined(__linux__)
  76.         case '1' : FSOUND_SetOutput(FSOUND_OUTPUT_OSS);
  77.         break;
  78.         case '2' : FSOUND_SetOutput(FSOUND_OUTPUT_ESD);
  79.         break;
  80.         case '3' : FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
  81.         break;
  82.         #endif
  83.         default : return 0;
  84.     }
  85.    
  86.     /*
  87.     SELECT OUTPUT DRIVER
  88.     */
  89.    
  90.     /* The following list are the drivers for the output method selected above. */
  91.     printf("---------------------------------------------------------\n" );
  92.     switch (FSOUND_GetOutput())
  93.     {
  94.         case FSOUND_OUTPUT_NOSOUND: printf("NoSound" ); break;
  95.         case FSOUND_OUTPUT_WINMM: printf("Windows Multimedia Waveout" ); break;
  96.         case FSOUND_OUTPUT_DSOUND: printf("Direct Sound" ); break;
  97.         case FSOUND_OUTPUT_OSS: printf("Open Sound System" ); break;
  98.         case FSOUND_OUTPUT_ESD: printf("Enlightment Sound Daemon" ); break;
  99.         case FSOUND_OUTPUT_ALSA: printf("ALSA" ); break;
  100.     };
  101.     printf(" Driver list\n" );
  102.     printf("---------------------------------------------------------\n" );
  103.    
  104.     for (i=0; i < FSOUND_GetNumDrivers(); i++)
  105.     {
  106.         printf("%d - %s\n", i+1, FSOUND_GetDriverName(i)); /* print driver names */
  107.     }
  108.     printf("---------------------------------------------------------\n" ); /* print driver names */
  109.     printf("Press a corresponding number or ESC to quit\n" );
  110.    
  111.     do
  112.     {
  113.         key = getch();
  114.         if (key == 27)
  115.         {
  116.             FSOUND_Close();
  117.             return 0;
  118.         }
  119.         driver = key - '1';
  120.     }
  121.     while (driver < 0 || driver >= FSOUND_GetNumDrivers());
  122.    
  123.     FSOUND_SetDriver(driver); /* Select sound card (0 = default) */
  124.    
  125.     /*
  126.     SELECT MIXER
  127.     */
  128.    
  129.     FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);
  130.    
  131.     /*
  132.     INITIALIZE
  133.     */
  134.     if (!FSOUND_Init(OUTPUTRATE, 64, FSOUND_INIT_ACCURATEVULEVELS))
  135.     {
  136.         printf("Error!\n" );
  137.         printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
  138.         return 0;
  139.     }
  140.    
  141.    
  142.     /*
  143.     SELECT INPUT DRIVER (can be done before or after init)
  144.     */
  145.    
  146.     /* The following list are the drivers for the output method selected above. */
  147.     printf("---------------------------------------------------------\n" );
  148.     switch (FSOUND_GetOutput())
  149.     {
  150.         case FSOUND_OUTPUT_NOSOUND: printf("NoSound" ); break;
  151.         case FSOUND_OUTPUT_WINMM: printf("Windows Multimedia Waveout" ); break;
  152.         case FSOUND_OUTPUT_DSOUND: printf("Direct Sound" ); break;
  153.         case FSOUND_OUTPUT_OSS: printf("Open Sound System" ); break;
  154.         case FSOUND_OUTPUT_ESD: printf("Enlightment Sound Daemon" ); break;
  155.         case FSOUND_OUTPUT_ALSA: printf("ALSA" ); break;
  156.     };
  157.     printf(" Recording device driver list\n" );
  158.     printf("---------------------------------------------------------\n" );
  159.    
  160.     for (i=0; i < FSOUND_Record_GetNumDrivers(); i++)
  161.     {
  162.         printf("%d - %s\n", i+1, FSOUND_Record_GetDriverName(i)); /* print driver names */
  163.     }
  164.     printf("---------------------------------------------------------\n" ); /* print driver names */
  165.     printf("Press a corresponding number or ESC to quit\n" );
  166.    
  167.     do
  168.     {
  169.         key = getch();
  170.         if (key == 27)
  171.         return 0;
  172.         driver = key - '1';
  173.     }
  174.     while (driver < 0 || driver >= FSOUND_Record_GetNumDrivers());
  175.    
  176.     if (!FSOUND_Record_SetDriver(driver)) /* Select input sound card (0 = default) */
  177.     {
  178.         printf("Error!\n" );
  179.         printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
  180.         FSOUND_Close();
  181.         return 0;
  182.     }
  183.    
  184.     /*
  185.     DISPLAY HELP
  186.     */
  187.    
  188.     printf("FSOUND Output Method : " );
  189.     switch (FSOUND_GetOutput())
  190.     {
  191.         case FSOUND_OUTPUT_NOSOUND: printf("FSOUND_OUTPUT_NOSOUND\n" ); break;
  192.         case FSOUND_OUTPUT_WINMM: printf("FSOUND_OUTPUT_WINMM\n" ); break;
  193.         case FSOUND_OUTPUT_DSOUND: printf("FSOUND_OUTPUT_DSOUND\n" ); break;
  194.         case FSOUND_OUTPUT_OSS: printf("FSOUND_OUTPUT_OSS\n" ); break;
  195.         case FSOUND_OUTPUT_ESD: printf("FSOUND_OUTPUT_ESD\n" ); break;
  196.         case FSOUND_OUTPUT_ALSA: printf("FSOUND_OUTPUT_ALSA\n" ); break;
  197.     };
  198.    
  199.     printf("FSOUND Mixer : " );
  200.     switch (FSOUND_GetMixer())
  201.     {
  202.         case FSOUND_MIXER_BLENDMODE: printf("FSOUND_MIXER_BLENDMODE\n" ); break;
  203.         case FSOUND_MIXER_MMXP5: printf("FSOUND_MIXER_MMXP5\n" ); break;
  204.         case FSOUND_MIXER_MMXP6: printf("FSOUND_MIXER_MMXP6\n" ); break;
  205.         case FSOUND_MIXER_QUALITY_FPU: printf("FSOUND_MIXER_QUALITY_FPU\n" ); break;
  206.         case FSOUND_MIXER_QUALITY_MMXP5:printf("FSOUND_MIXER_QUALITY_MMXP5\n" ); break;
  207.         case FSOUND_MIXER_QUALITY_MMXP6:printf("FSOUND_MIXER_QUALITY_MMXP6\n" ); break;
  208.     };
  209.     printf("FSOUND Driver : %s\n", FSOUND_GetDriverName(FSOUND_GetDriver()));
  210.     printf("FSOUND Record Driver : %s\n", FSOUND_Record_GetDriverName(FSOUND_Record_GetDriver()));
  211.    
  212.     // My stream for my synthetiseur circuit (wich need to be feeded by the micro)
  213.     stream = FSOUND_Stream_Create(instrument_callback, BufferSize, FSOUND_16BITS | FSOUND_SIGNED | FSOUND_STEREO |FSOUND_NONBLOCKING, Frequency, (void *)NULL);
  214.     if (!stream)
  215.     {
  216.         printf("Error!\n" );
  217.         printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
  218.         exit(1);
  219.     }
  220.     // Play the synthetiseur channel cause we wanna hear some good sounds
  221.     if (FSOUND_Stream_Play(FSOUND_FREE, stream) == -1) {printf("Error!\n" );printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));exit(1);}
  222.    
  223.     /*
  224.     Create a sample to record into
  225.     */
  226.     if (FSOUND_GetOutput() == FSOUND_OUTPUT_OSS)
  227.     {
  228.         samp1 = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, RECORDLEN, FSOUND_MONO | FSOUND_8BITS | FSOUND_UNSIGNED, RECORDRATE, 255, 128, 255);
  229.     }
  230.     else
  231.     {
  232.         samp1 = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, RECORDLEN, FSOUND_STEREO | FSOUND_16BITS , RECORDRATE, 255, 128, 255);
  233.     }
  234.    
  235.     printf("\n" );
  236.     printf("=========================================================================\n" );
  237.     printf("Press a key to start recording 5 seconds worth of data\n" );
  238.     printf("=========================================================================\n" );
  239.    
  240.     if (!FSOUND_Record_StartSample(samp1, FALSE)) /* it will record into this sample for 5 seconds then stop */
  241.     {
  242.         printf("Error!\n" );
  243.         printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
  244.         FSOUND_Close();
  245.         return 0;
  246.     }
  247.    
  248.    
  249.     FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_NORMAL); /* make it a looping sample */
  250.     if (!FSOUND_Record_StartSample(samp1, TRUE)) /* start recording and make it loop also */
  251.     {
  252.         printf("Error!\n" );
  253.         printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
  254.        
  255.         FSOUND_Close();
  256.         return 0;
  257.     }
  258.     while(1); 
  259.     FSOUND_StopSound(channel);
  260.     FSOUND_Record_Stop();
  261.     FSOUND_Sample_Free(samp1);
  262.     FSOUND_Close();
  263.     return 0;
  264. // FIN DU MAIN
  265. }
  266. // This Came From Brett, The super man of Fmod
  267. // Retour : Position a jouer (car dernier morceau copie)
  268. int copie_Sample_Micro_vers_ring_buffer_micro()
  269. {
  270.     static int oldposition = 0;
  271.     int newposition = FSOUND_Record_GetPosition();
  272.     int offs=0;
  273.     if (newposition != oldposition)
  274.     {
  275.         void *ptr1, *ptr2;
  276.         unsigned int len1, len2;
  277.         int length = newposition - oldposition;
  278.         if (length < 0) // new position might have wrapped around to 0!
  279.         {
  280.             length += FSOUND_Sample_GetLength(samp1);
  281.         }
  282.         FSOUND_Sample_Lock(samp1, oldposition * 4, length * 4, &ptr1, &ptr2, &len1, &len2); // *4 = 16bit stereo
  283.        
  284.         offs=myoffset_bytes;
  285.         if (myoffset_bytes + len1 <= mylength_bytes)
  286.         {
  287.             memcpy(mybuffer + myoffset_bytes, ptr1, len1);
  288.             myoffset_bytes += len1;
  289.         }
  290.         else
  291.         {
  292.             // mybuffer wraps around
  293.             memcpy(mybuffer + myoffset_bytes, ptr1, mylength_bytes - myoffset_bytes);
  294.             // memcpy(mybuffer, ptr1 + (mylength_bytes - myoffset_bytes), len1 - (mylength_bytes - myoffset_bytes));
  295.             memcpy(mybuffer,
  296.             (signed short*)ptr1 + (mylength_bytes - myoffset_bytes),
  297.             len1 - (mylength_bytes - myoffset_bytes)
  298.             );
  299.            
  300.             myoffset_bytes += len1;
  301.             myoffset_bytes -= mylength_bytes;
  302.         }
  303.        
  304.         if (len2)
  305.         {
  306.             if (myoffset_bytes + len2 <= mylength_bytes)
  307.             {
  308.                 memcpy(mybuffer + myoffset_bytes, ptr2, len2);
  309.                 myoffset_bytes += len2;
  310.             }
  311.             else
  312.             {
  313.                 // mybuffer wraps around
  314.                 memcpy(mybuffer + myoffset_bytes, ptr2, mylength_bytes - myoffset_bytes);
  315.                 memcpy(mybuffer, (signed short*)ptr2 + (mylength_bytes - myoffset_bytes), len2 - (mylength_bytes - myoffset_bytes));
  316.                
  317.                 myoffset_bytes += len2;
  318.                 myoffset_bytes -= mylength_bytes;
  319.             }
  320.         }
  321.    
  322.         FSOUND_Sample_Unlock(samp1, ptr1, ptr2, len1, len2);
  323.        
  324.         oldposition += length;
  325.         if (oldposition >= FSOUND_Sample_GetLength(samp1) )
  326.         {
  327.             oldposition -= FSOUND_Sample_GetLength(samp1);
  328.         }
  329.     }
  330.     return(offs);
  331. }
  332.    
  333. signed char F_CALLBACKAPI instrument_callback(FSOUND_STREAM *stream, void *buff, int len, void *param) {
  334. {
  335.     static float MX=0;
  336.     signed short *stereo16bitbuffer = (signed short *)buff;
  337.     static float t=0,dx=0;
  338.     int i=0;
  339.     int channel=0;
  340.     // I do it there to be sure of the sync, it seem to work not less than if that were in main ...
  341.     int offs = copie_Sample_Micro_vers_ring_buffer_micro();
  342.     float osc_result= 0;
  343.     for (float x=0;x<len>>2;x++)
  344.     {
  345.         t++;
  346.         // Obtain actual micro value (to normally give it to synth but not there)
  347.         MICRO_INPUT = (signed short)mybuffer[(int)offs];
  348.         // Here normally i generate sound with my synthesizer class, but i brief a lot ...
  349.         //osc_result=(float)(rand()%100)/100; // For Tv like Noise
  350.         osc_result=sin(t*2*PI/180); // For Sinusoidal VCO
  351.        
  352.        
  353.         // I modulate the Synth signal with MicroInput in this exemple (AM)
  354.         *stereo16bitbuffer = ((float)MICRO_INPUT/32767)*(osc_result*32767);
  355.         *(stereo16bitbuffer+1) =((float)MICRO_INPUT/32767)*(osc_result*32767);
  356.        
  357.         // Fait avancer le ring buffer du micro et evite le depassement (ring buffer offset++)
  358.         offs+=2;
  359.         if((offs >= mylength_bytes) && (offs < 0) )
  360.         {
  361.            offs = 0;
  362.         }
  363.         stereo16bitbuffer+=2;
  364.     }
  365. }
  366.     return(1);
  367. }


Message édité par l3eleg le 24-05-2006 à 13:37:47
Reply

Marsh Posté le 24-05-2006 à 13:35:47   

Reply

Marsh Posté le 26-05-2006 à 14:39:20    

Ecris la solution que je t'ai donnée tiens, ca pourra aider des gens ;)

Reply

Marsh Posté le 19-02-2008 à 17:07:39    

Salut !
 
Si vous avez une solution pour le découpage en 0,1 ms je suis preneur !
Merci .

Reply

Marsh Posté le 23-02-2010 à 10:16:27    

Bonjour,
 
Je suis également très intéressé par la réponse à cette question !
 
Merci,
Mathieu

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed