Fmod, probleme avec channel->getSpectrum()

Fmod, probleme avec channel->getSpectrum() - C++ - Programmation

Marsh Posté le 26-05-2006 à 12:11:59    

bonjour à tous,
je cherche à obtenir le spectre d'un fichier wav ouvert sous mathlab, afin d'effectuer une analyse spectrale visant à identifier les notes. J'ai besoin de quelqu'un ayant déjà utiliser FMODex auparavant.
Je me base sur l'exemple d'fmodex s'intitulant "pitchdetection", cet exemple permet d'effectuer une FFT sur le signal et d'en déduire le spectre.
 

Code :
  1. /*===============================================================================================
  2. Pitch detection example.
  3. Copyright (c), Firelight Technologies Pty, Ltd 2004-2005.
  4. This example combines recording with spectrum analysis to determine the pitch of the sound
  5. being recorded.
  6. ===============================================================================================*/
  7. #include "inc/fmod.hpp"
  8. #include "inc/fmod_errors.h"
  9. #include <windows.h>
  10. #include <stdio.h>
  11. #include <conio.h>
  12. #include <math.h>
  13. void ERRCHECK(FMOD_RESULT result, int i)
  14. {
  15.     if (result != FMOD_OK)
  16.     {
  17.         printf("(l:%i) FMOD error! (%d) %s\n", i, result, FMOD_ErrorString(result));
  18.         exit(-1);
  19.     }
  20. }
  21. static const char *note[120] =
  22. {
  23.     "C 0", "C#0", "D 0", "D#0", "E 0", "F 0", "F#0", "G 0", "G#0", "A 0", "A#0", "B 0", 
  24.     "C 1", "C#1", "D 1", "D#1", "E 1", "F 1", "F#1", "G 1", "G#1", "A 1", "A#1", "B 1", 
  25.     "C 2", "C#2", "D 2", "D#2", "E 2", "F 2", "F#2", "G 2", "G#2", "A 2", "A#2", "B 2", 
  26.     "C 3", "C#3", "D 3", "D#3", "E 3", "F 3", "F#3", "G 3", "G#3", "A 3", "A#3", "B 3", 
  27.     "C 4", "C#4", "D 4", "D#4", "E 4", "F 4", "F#4", "G 4", "G#4", "A 4", "A#4", "B 4", 
  28.     "C 5", "C#5", "D 5", "D#5", "E 5", "F 5", "F#5", "G 5", "G#5", "A 5", "A#5", "B 5", 
  29.     "C 6", "C#6", "D 6", "D#6", "E 6", "F 6", "F#6", "G 6", "G#6", "A 6", "A#6", "B 6", 
  30.     "C 7", "C#7", "D 7", "D#7", "E 7", "F 7", "F#7", "G 7", "G#7", "A 7", "A#7", "B 7", 
  31.     "C 8", "C#8", "D 8", "D#8", "E 8", "F 8", "F#8", "G 8", "G#8", "A 8", "A#8", "B 8", 
  32.     "C 9", "C#9", "D 9", "D#9", "E 9", "F 9", "F#9", "G 9", "G#9", "A 9", "A#9", "B 9"
  33. };
  34. static const float notefreq[120] =
  35. {
  36.       16.35f,   17.32f,   18.35f,   19.45f,    20.60f,    21.83f,    23.12f,    24.50f,    25.96f,    27.50f,    29.14f,    30.87f,
  37.       32.70f,   34.65f,   36.71f,   38.89f,    41.20f,    43.65f,    46.25f,    49.00f,    51.91f,    55.00f,    58.27f,    61.74f,
  38.       65.41f,   69.30f,   73.42f,   77.78f,    82.41f,    87.31f,    92.50f,    98.00f,   103.83f,   110.00f,   116.54f,   123.47f,
  39.      130.81f,  138.59f,  146.83f,  155.56f,   164.81f,   174.61f,   185.00f,   196.00f,   207.65f,   220.00f,   233.08f,   246.94f,
  40.      261.63f,  277.18f,  293.66f,  311.13f,   329.63f,   349.23f,   369.99f,   392.00f,   415.30f,   440.00f,   466.16f,   493.88f,
  41.      523.25f,  554.37f,  587.33f,  622.25f,   659.26f,   698.46f,   739.99f,   783.99f,   830.61f,   880.00f,   932.33f,   987.77f,
  42.     1046.50f, 1108.73f, 1174.66f, 1244.51f,  1318.51f,  1396.91f,  1479.98f,  1567.98f,  1661.22f,  1760.00f,  1864.66f,  1975.53f,
  43.     2093.00f, 2217.46f, 2349.32f, 2489.02f,  2637.02f,  2793.83f,  2959.96f,  3135.96f,  3322.44f,  3520.00f,  3729.31f,  3951.07f,
  44.     4186.01f, 4434.92f, 4698.64f, 4978.03f,  5274.04f,  5587.65f,  5919.91f,  6271.92f,  6644.87f,  7040.00f,  7458.62f,  7902.13f,
  45.     8372.01f, 8869.84f, 9397.27f, 9956.06f, 10548.08f, 11175.30f, 11839.82f, 12543.85f, 13289.75f, 14080.00f, 14917.24f, 15804.26f
  46. };
  47. #define OUTPUTRATE          44100
  48. #define SPECTRUMSIZE        8192
  49. #define SPECTRUMRANGE       ((float)OUTPUTRATE / 2.0f)      /* 0 to nyquist */
  50. #define BINSIZE      (SPECTRUMRANGE / (float)SPECTRUMSIZE)
  51. int main(int argc, char *argv[])
  52. {
  53.     FMOD::System          *system  = 0;
  54.     FMOD::Sound           *sound   = 0;
  55. FMOD::Sound     *sound2  = 0;
  56.     FMOD::Channel         *channel = 0;
  57.     FMOD::Channel         *channel2 = 0;
  58.     FMOD_RESULT            result;
  59.     FMOD_CREATESOUNDEXINFO exinfo;
  60.     int                    key, driver, numdrivers, count, bin;
  61.     unsigned int           version;   
  62. int        i=0;
  63.     /*
  64.         Create a System object and initialize.
  65.     */
  66.     result = FMOD::System_Create(&system);
  67.     ERRCHECK(result,1);
  68.     result = system->getVersion(&version);
  69.     ERRCHECK(result,2);
  70.     if (version < FMOD_VERSION)
  71.     {
  72.         printf("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
  73.         return 0;
  74.     }
  75.     /*  
  76.         System initialization
  77.     */
  78.     printf("---------------------------------------------------------\n" );   
  79.     printf("Select OUTPUT type\n" );   
  80.     printf("---------------------------------------------------------\n" );   
  81.     printf("1 :  DirectSound\n" );
  82.     printf("2 :  Windows Multimedia WaveOut\n" );
  83.     printf("3 :  ASIO\n" );
  84.     printf("---------------------------------------------------------\n" );
  85.     printf("Press a corresponding number or ESC to quit\n" );
  86.     do
  87.     {
  88.         key = getch();
  89.     } while (key != 27 && key < '1' && key > '5');
  90.    
  91.     switch (key)
  92.     {
  93.         case '1' :  result = system->setOutput(FMOD_OUTPUTTYPE_DSOUND);
  94.                     break;
  95.         case '2' :  result = system->setOutput(FMOD_OUTPUTTYPE_WINMM);
  96.                     break;
  97.         case '3' :  result = system->setOutput(FMOD_OUTPUTTYPE_ASIO);
  98.                     break;
  99.         default  :  return 1;
  100.     } 
  101.     ERRCHECK(result,3);
  102.    
  103.     /*
  104.         Enumerate playback devices
  105.     */
  106.     result = system->getNumDrivers(&numdrivers);
  107.     ERRCHECK(result,4);
  108.     printf("---------------------------------------------------------\n" );   
  109.     printf("Choose a PLAYBACK driver\n" );
  110.     printf("---------------------------------------------------------\n" );   
  111.     for (count=0; count < numdrivers; count++)
  112.     {
  113.         char name[256];
  114.         result = system->getDriverName(count, name, 256);
  115.         ERRCHECK(result,5);
  116.         printf("%d : %s\n", count + 1, name);
  117.     }
  118.     printf("---------------------------------------------------------\n" );
  119.     printf("Press a corresponding number or ESC to quit\n" );
  120.     do
  121.     {
  122.         key = getch();
  123.         if (key == 27)
  124.         {
  125.             return 0;
  126.         }
  127.         driver = key - '1';
  128.     } while (driver < 0 || driver >= numdrivers);
  129.     result = system->setDriver(driver);
  130.     ERRCHECK(result,6);
  131.     /*
  132.         Enumerate record devices
  133.     */
  134.     result = system->getRecordNumDrivers(&numdrivers);
  135.     ERRCHECK(result,7);
  136.     printf("---------------------------------------------------------\n" );   
  137.     printf("Choose a RECORD driver\n" );
  138.     printf("---------------------------------------------------------\n" );   
  139.     for (count=0; count < numdrivers; count++)
  140.     {
  141.         char name[256];
  142.         result = system->getRecordDriverName(count, name, 256);
  143.         ERRCHECK(result,8);
  144.         printf("%d : %s\n", count + 1, name);
  145.     }
  146.     printf("---------------------------------------------------------\n" );
  147.     printf("Press a corresponding number or ESC to quit\n" );
  148.     do
  149.     {
  150.         key = getch();
  151.         if (key == 27)
  152.         {
  153.             return 0;
  154.         }
  155.         driver = key - '1';
  156.     } while (driver < 0 || driver >= numdrivers);
  157.     printf("\n" );
  158.     result = system->setRecordDriver(driver);
  159.     ERRCHECK(result,9);
  160.     result = system->setSoftwareFormat(OUTPUTRATE, FMOD_SOUND_FORMAT_PCM16, 1, 0, FMOD_DSP_RESAMPLER_LINEAR);
  161.     ERRCHECK(result,10);
  162.     result = system->init(32, FMOD_INIT_NORMAL, 0);
  163.     ERRCHECK(result,11);
  164.     /*
  165.         Create a sound to record to.
  166.     */
  167.     memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
  168.     exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO);
  169.     exinfo.numchannels      = 1;
  170.     exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
  171.     exinfo.defaultfrequency = OUTPUTRATE;
  172.     exinfo.length           = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 5;
  173.    
  174.     result = system->createSound(0, FMOD_2D | FMOD_SOFTWARE | FMOD_LOOP_NORMAL | FMOD_OPENUSER, &exinfo, &sound);
  175.     ERRCHECK(result,12);
  176. result = system->createSound("do.wav", FMOD_2D | FMOD_SOFTWARE, &exinfo, &sound2);
  177.     ERRCHECK(result,13);
  178.     /*
  179.         Start the interface
  180.     */
  181.     printf("=========================================================================\n" );
  182.     printf("Pitch detection example.  Copyright (c) Firelight Technologies 2004-2005.\n" );
  183.     printf("=========================================================================\n" );
  184.     printf("\n" );
  185.     printf("Record something through the selected recording device and FMOD will\n" );
  186.     printf("Determine the pitch.  Sustain the tone for at least a second to get an\n" );
  187.     printf("accurate reading.\n" );
  188.     printf("Press 'Esc' to quit\n" );
  189.     printf("\n" );
  190.     result = system->recordStart(sound, true);
  191.     ERRCHECK(result,14);
  192.    
  193.     Sleep(200);      /* Give it some time to record something */
  194.    
  195. result = system->playSound(FMOD_CHANNEL_FREE, sound2, false, &channel2);
  196.     ERRCHECK(result,15);
  197.     result = system->playSound(FMOD_CHANNEL_REUSE, sound, false, &channel);
  198.     ERRCHECK(result,16);
  199.     /* Dont hear what is being recorded otherwise it will feedback.  Spectrum analysis is done before volume scaling in the DSP chain */
  200.     result = channel2->setVolume(0);
  201.     ERRCHECK(result,17);
  202.     bin = 0;
  203.     /*
  204.         Main loop.
  205.     */
  206.     do
  207.     {
  208.         static float spectrum[SPECTRUMSIZE];
  209.         float        dominanthz = 0;
  210.         float        max;
  211.         int          dominantnote = 0;
  212.         float        binsize = BINSIZE;
  213.         if (kbhit())
  214.         {
  215.             key = getch();
  216.         }
  217.         result = channel2->getSpectrum(spectrum, SPECTRUMSIZE, 0, FMOD_DSP_FFT_WINDOW_TRIANGLE);
  218.         ERRCHECK(result,18);
  219.         max = 0;
  220.         for (count = 0; count < SPECTRUMSIZE; count++)
  221.         {
  222.             if (spectrum[count] > 0.01f && spectrum[count] > max)
  223.             {
  224.                 max = spectrum[count];
  225.                 bin = count;
  226.             }
  227.         }       
  228.         dominanthz  = (float)bin * BINSIZE;       /* dominant frequency min */
  229.         dominantnote = 0;
  230.         for (count = 0; count < 120; count++)
  231.         {
  232.              if (dominanthz >= notefreq[count] && dominanthz < notefreq[count + 1])
  233.              {
  234.                 /* which is it closer to.  This note or the next note */
  235.                 if (fabs(dominanthz - notefreq[count]) < fabs(dominanthz - notefreq[count+1]))
  236.                 {
  237.                     dominantnote = count;
  238.                 }
  239.                 else
  240.                 {
  241.                     dominantnote = count + 1;
  242.                 }
  243.                 break;
  244.              }
  245.         }
  246.         printf("Detected rate : %7.1f -> %7.1f hz.  Detected musical note. %-3s (%7.1f hz)\r", dominanthz, ((float)bin + 0.99f) * BINSIZE, note[dominantnote], notefreq[dominantnote]);
  247.         system->update();
  248.         Sleep(10);
  249.     } while (key != 27);
  250.     printf("\n" );
  251.     /*
  252.         Shut down
  253.     */
  254.     result = sound->release();
  255.     ERRCHECK(result,17);
  256.     result = system->release();
  257.     ERRCHECK(result,18);
  258.     return 0;
  259. }


 
 
On ouvre donc le fichier do.wav, jusque ici aucun probleme, on le définit en FMOD_SOFTWARE sinon getSpectrum ne fonctionne pas

Code :
  1. result = system->createSound("do.wav", FMOD_2D | FMOD_SOFTWARE, &exinfo, &sound2);
  2.     ERRCHECK(result,13);


 
Le problème se situe donc ici :

Code :
  1. result = channel2->getSpectrum(spectrum, SPECTRUMSIZE, 0, FMOD_DSP_FFT_WINDOW_TRIANGLE);
  2.         ERRCHECK(result,18);


Si je soumet a getSpectrum le channel2 (le fichier wav) le programme plante lors de l'execution (erreur memoire), si je founis channel (l'entrée micro) tout marche parfaitement (mais je ne peux pas analyser le fichier son forcément ... :p)
 
Quelqu'un a déjà essayer de faire cela ?

Reply

Marsh Posté le 26-05-2006 à 12:11:59   

Reply

Marsh Posté le 28-05-2006 à 16:35:39    

à vue de nez, tu as un problème avec le format de fichier son.
vérifie que tu alloue bien la quantité de mémoire necessaire suivant la taille de l'échantillonage.

Reply

Marsh Posté le 06-06-2006 à 13:32:26    

Bonjour, j'ai egalement un probleme avec le GetSpectrum. Je code une visualisation des frequences d'une musique, en C et opengl. J'arrive à lire la musique, mais si dans ma boucle principale j execute Channel_GetSpectrum avec les bons arguments, le programme segfault.
 
De plus gdb me dit que le segfault se produit lors de l appel a cette derniere fonction.
 
La documentation fournie a l air deprecated, et je trouve peu d aide sur google et pourtant le temps presse !
 
Alors aurais je oublié d'activer quelque chose ?peut etre ai je mal compris comment utiliser cette fonction ?
 
Dans l'attente d'une reponse precise (>2lignes), je vous remercie de l aide que vous saurez m apporter!

Reply

Sujets relatifs:

Leave a Replay

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