Autor Tema: Player de archivos WAV en AT91SAM7S con FreeRTOS  (Leído 2420 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Player de archivos WAV en AT91SAM7S con FreeRTOS
« en: 05 de Noviembre de 2009, 01:10:01 »
Habiendo armado un Driver de Fat FS para AT91SAM7S sobre FreeRTOS y KEIL y un Driver de I2S (SSC) para AT91SAM7S sobre FreeRTOS y KEIL estabamos a un paso de reproducir archivos de audio con el sistemita asi que investigue un poco el formato de archivos WAV y conforme la demo simple.


Como veran el main que maneja el ejemplo es extremadamente simple, la complejidad esta escondida "debajo del capot"
Código: C
  1. /* Scheduler include files. */
  2. #include "FreeRTOS.h"
  3. #include "task.h"
  4.  
  5. /* Hardware specific headers */
  6. #include "common\board.h"
  7.  
  8. /*Modules Header files*/
  9. #include "i2s\i2s.h"
  10. #include "rtc\rtcTask.h"
  11. #include "fatfs\ff.h"
  12. #include "fatfs\diskio.h"
  13. #include "audioFile\audioFile.h"
  14.  
  15. /*Global const*/
  16.  
  17. /*Defines*/
  18.  
  19. /*Global vars*/
  20. //Data for the demo task
  21. static xTaskHandle xAudioFileDemoHandle;
  22.  
  23. //For the Filesystem
  24. static FATFS fs;            // Work area (file system object) for logical drive
  25. static FIL audioFile;       // file object
  26. static FRESULT res;         // FatFs function common result code
  27. static UINT br;                 // File R/W count
  28. static portCHAR buffer[512];
  29. #define SIZEOFBUFFER (sizeof(buffer) / 2)
  30.  
  31. //For Audio DAC I2S
  32. static tI2sInitData xInitData;
  33. static tI2sSendData xSendData;
  34.  
  35. //For AudioFile
  36. portCHAR *pBuffer = NULL;
  37.  
  38. /*Functions and Tasks*/
  39. static void prvSetupHardware( void );
  40. static void vAudioFileDemo( void *pvParameters );
  41.  
  42. /*Main Program*/
  43. int main( void )
  44. {  
  45.     /* Setup the ports */
  46.     prvSetupHardware();
  47.  
  48.     /*Start and Init RTC*/
  49.     vRtcTaskStart();
  50.        
  51.     /*Tasks Start-up*/
  52.     xTaskCreate( vAudioFileDemo, "AudioFileDemo", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xAudioFileDemoHandle );
  53.  
  54.     /*Start the scheduler.*/
  55.     vTaskStartScheduler();
  56.  
  57.     /* Should never get here! */
  58.     return 0;
  59. }
  60.  
  61. /*A Demo of the features in the Graphic LCD driver for FreeRTOS*/
  62. static void vAudioFileDemo( void *pvParameters )
  63. {
  64.     for ( ; ; )
  65.     {
  66.       // Register a work area for logical drive 0
  67.       res = f_mount(0, &fs);
  68.       if (res) goto vAudioFileDemo_finish;
  69.  
  70.       //Open a file
  71.       res = f_open(&audioFile, "audio.wav", FA_OPEN_EXISTING | FA_READ);
  72.       if (res) goto vAudioFileDemo_close;
  73.  
  74.                 //Read file header
  75.                 res = f_read(&audioFile, buffer, sizeof(tAfFormatChunk), &br);
  76.       if (res) goto vAudioFileDemo_close;
  77.  
  78.       //Prepare DAC
  79.                 xInitData.config.slotByFrame = 2;
  80.       xInitData.config.bitsBySLot = CHUNK_WAV_GET_BITRES(buffer);
  81.       xInitData.config.samplingFreq = CHUNK_WAV_GET_FREQUENCY(buffer);
  82.       xInitData.config.rxEnabled = 0;
  83.       xInitData.config.txEnabled = 1;
  84.  
  85.       //Because mono wav is going to be shared between 2 channel we lower the bitrate to the half
  86.       if (CHUNK_WAV_GET_CHANNELS(buffer) == 1) xInitData.config.samplingFreq /= 2;
  87.  
  88.                 //Init Device
  89.       eI2sInit(&xInitData);
  90.  
  91.                 //Set Block time
  92.                 xSendData.xBlockTime = 30;
  93.  
  94.                 vAudioFileDemo_file_loop:
  95.                
  96.                 //Read data from file
  97.       do
  98.       {
  99.          if (pBuffer == buffer) pBuffer = &buffer[SIZEOFBUFFER];
  100.                         else pBuffer = buffer;
  101.  
  102.                         res = f_read(&audioFile, pBuffer, SIZEOFBUFFER, &br);
  103.          if (res) goto vAudioFileDemo_close;
  104.          
  105.          //Prepare data for audio buffer
  106.                         xSendData.size = br/2;
  107.                         xSendData.data = (const unsigned portCHAR *) pBuffer;
  108.  
  109.                         //Send frame to the i2s buffer
  110.          cSendFrame(&xSendData);
  111.       }
  112.                 while (br == SIZEOFBUFFER);
  113.  
  114.       res = f_lseek(&audioFile, sizeof(tAfFormatChunk));
  115.                 if (res) goto vAudioFileDemo_close;
  116.  
  117.                 goto vAudioFileDemo_file_loop;
  118.    
  119.       vAudioFileDemo_close:
  120.       f_close(&audioFile);
  121.  
  122.       // Unregister a work area before discard it
  123.       f_mount(0, NULL);
  124.        
  125.       vAudioFileDemo_finish:  
  126.       vTaskDelete(xAudioFileDemoHandle);
  127.    }
  128. }
  129.  
  130. static void prvSetupHardware( void )
  131. {
  132.     /* When using the JTAG debugger the hardware is not always initialised to
  133.     the correct default state.  This line just ensures that this does not
  134.     cause all interrupts to be masked at the start. */
  135.     AT91C_BASE_AIC->AIC_EOICR = 0;
  136.    
  137.     /* Enable the peripheral clock to the PIO */
  138.     AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_PIOA);
  139. }

En este ejemplo se reproduce un archivo de sonido (play.wav), identificando la conformacion de los datos a traves de la lectura del header del mismo.

Código: C
  1. typedef struct
  2. {
  3.  
  4.   portLONG     RIFF;       //RIFF header
  5.   portCHAR     NI1 [18];   //not important
  6.   portSHORT    sChannels;  //channels 1 = mono; 2 = stereo
  7.   portLONG     lFrequency; //sample frequency
  8.   portLONG     lByteRate;  //Byte Rate
  9.   portSHORT    sBlockAlign;//Block Align
  10.   portCHAR     cBitRes;    //bit resolution 8/16 bit      
  11.   portCHAR     NI3 [12];   //not important                  
  12.  
  13. } tAfFormatChunk, *pAfFormatChunk;
  14.  
  15. /*Macro definitions*/
  16. #define CHUNK_WAV_GET_CHANNELS(x)   ((pAfFormatChunk)  x)->sChannels;
  17. #define CHUNK_WAV_GET_BITRES(x)     ((pAfFormatChunk)  x)->cBitRes;
  18. #define CHUNK_WAV_GET_FREQUENCY(x)  ((pAfFormatChunk)  x)->lFrequency;
  19. #define CHUNK_WAV_GET_BLOCKALIGN(x) ((pAfFormatChunk)  x)->sBlockAlign;
  20. #define CHUNK_WAV_IS_RIFF(x)        (((pAfFormatChunk) x)->RIFF == 0x46464952)

Video:

Link al codigo:
archivo zip con las src
Se lee de a multiples chunks hasta agotar el file y se empieza nuevamente.

Saludos espero que les agrade.

PD: Mas adelante se puede completar mas leyendo la lista de archivos en el root y reproduciendolos secuencialmente.
« Última modificación: 05 de Noviembre de 2009, 22:36:50 por Darukur »
El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/


Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #2 en: 05 de Noviembre de 2009, 15:56:58 »
Excelente proyecto esta a años luz de lo que yo soy capas de hacer   8)

Desconectado nico

  • PIC16
  • ***
  • Mensajes: 180
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #3 en: 05 de Noviembre de 2009, 17:28:54 »
Exelente Darukur, y ademàs aprovecho para felicitarte, exelente tu web....

Saludos....

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #4 en: 05 de Noviembre de 2009, 22:38:49 »
Gracias! Ahi corregi el codigo ya que estaba innecesariamente reordenando los datos porque habia malinterpretado el header de WAV.
Cambie el videito tambien, como se puede ver hay un tema de desgarros del audio, tengo que analizarlo pero estoy casi seguro que es algun tema en la lectura desde SD.

Salutes.

Darukur
El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #5 en: 05 de Noviembre de 2009, 23:50:15 »
pffff

 :shock: :shock:

Eres un monstruo !!!!!

Excelente.
El papel lo aguanta todo

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #6 en: 05 de Noviembre de 2009, 23:53:17 »
Super interesante el proyecto!! Que DAC I2S utilizaste? Porque estaba viendo el de National Semiconductor y es imposible soldarlo  :8}

Felicitaciones!!
No contesto mensajes privados, las consultas en el foro

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #7 en: 06 de Noviembre de 2009, 01:09:19 »
Esta demo nueva lee el root del disco y lista los files, los que encuentre con cabecera WAV (no le interesa la extension) los reproduce.

Código: C
  1. /* Scheduler include files. */
  2. #include "FreeRTOS.h"
  3. #include "task.h"
  4.  
  5. /* Hardware specific headers */
  6. #include "common\board.h"
  7.  
  8. /*Modules Header files*/
  9. #include "i2s\i2s.h"
  10. #include "rtc\rtcTask.h"
  11. #include "fatfs\ff.h"
  12. #include "fatfs\diskio.h"
  13. #include "audioFile\audioFile.h"
  14.  
  15. /*Global const*/
  16.  
  17. /*Defines*/
  18.  
  19. /*Global vars*/
  20. //Data for the demo task
  21. static xTaskHandle xAudioFileDemoHandle;
  22.  
  23. //For the Filesystem
  24. static FATFS fs;            // Work area (file system object) for logical drive
  25. static FIL audioFile;       // File object
  26. static DIR dir;             // Firectory object
  27. static FILINFO fno;         // File Information
  28. static FRESULT res;         // FatFs function common result code
  29. static UINT br;             // File R/W count
  30. static portCHAR buffer[512];
  31. #define SIZEOFBUFFER (sizeof(buffer) / 2)
  32.  
  33. //For Audio DAC I2S
  34. static tI2sInitData xInitData;
  35. static tI2sSendData xSendData;
  36.  
  37. //For AudioFile
  38. portCHAR *pBuffer = NULL;
  39.  
  40. /*Functions and Tasks*/
  41. static void prvSetupHardware( void );
  42. static void vAudioFileDemo( void *pvParameters );
  43.  
  44. /*Main Program*/
  45. int main( void )
  46. {  
  47.     /* Setup the ports */
  48.     prvSetupHardware();
  49.  
  50.     /*Start and Init RTC*/
  51.     vRtcTaskStart();
  52.        
  53.     /*Tasks Start-up*/
  54.     xTaskCreate( vAudioFileDemo, "AudioFileDemo", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xAudioFileDemoHandle );
  55.  
  56.     /*Start the scheduler.*/
  57.     vTaskStartScheduler();
  58.  
  59.     /* Should never get here! */
  60.     return 0;
  61. }
  62.  
  63. /*A Demo of the features in the Graphic LCD driver for FreeRTOS*/
  64. static void vAudioFileDemo( void *pvParameters )
  65. {
  66.     portCHAR cnt;
  67.     for ( ; ; )
  68.     {
  69.       // Register a work area for logical drive 0
  70.       res = f_mount(0, &fs);
  71.       if (res) goto vAudioFileDemo_finish;
  72.  
  73.       //Open directory
  74.       res = f_opendir(&dir, "/");
  75.       if (res != FR_OK) goto vAudioFileDemo_umount;
  76.  
  77.       while (1)
  78.       {
  79.          //Read a Directory entry
  80.          res = f_readdir(&dir, &fno);
  81.          if (res != FR_OK || fno.fname[0] == 0) goto vAudioFileDemo_umount;
  82.          if (fno.fname[0] == '.') continue;
  83.  
  84.          //Open a file
  85.          res = f_open(&audioFile, fno.fname, FA_OPEN_EXISTING | FA_READ);
  86.          if (res) goto vAudioFileDemo_close;
  87.  
  88.          //Read file header
  89.          res = f_read(&audioFile, buffer, sizeof(tAfFormatChunk), &br);
  90.          if (res) goto vAudioFileDemo_close;
  91.  
  92.          //Check for WAV file
  93.          if (!CHUNK_WAV_IS_RIFF(buffer) || !CHUNK_WAV_IS_WAVE(buffer)) continue;
  94.  
  95.          //Prepare DAC
  96.          xInitData.config.slotByFrame = 2;
  97.          xInitData.config.bitsBySLot = CHUNK_WAV_GET_BITRES(buffer);
  98.          xInitData.config.samplingFreq = CHUNK_WAV_GET_FREQUENCY(buffer);
  99.          xInitData.config.rxEnabled = 0;
  100.          xInitData.config.txEnabled = 1;
  101.  
  102.          //Because mono wav is going to be shared between 2 channel we lower the bitrate to the half
  103.          if (CHUNK_WAV_GET_CHANNELS(buffer) == 1) xInitData.config.samplingFreq /= 2;
  104.  
  105.          //Init I2S Device with selected configuration
  106.          eI2sInit(&xInitData);
  107.  
  108.          //Set I2s task Block time
  109.          xSendData.xBlockTime = 30;
  110.  
  111.          //Loop the file n times
  112.          for (cnt = 0; cnt < 4; cnt ++)
  113.          {
  114.             //Seek to the begining of the audio data
  115.             res = f_lseek(&audioFile, sizeof(tAfFormatChunk));
  116.             if (res) goto vAudioFileDemo_close;
  117.  
  118.             //Read data from file
  119.             do
  120.             {
  121.                if (pBuffer == buffer) pBuffer = &buffer[SIZEOFBUFFER];
  122.                else pBuffer = buffer;
  123.      
  124.                res = f_read(&audioFile, pBuffer, SIZEOFBUFFER, &br);
  125.                if (res) goto vAudioFileDemo_close;
  126.                
  127.                //Prepare data for audio buffer
  128.                xSendData.size = br/2;
  129.                xSendData.data = (const unsigned portCHAR *) pBuffer;
  130.      
  131.                //Send frame to the i2s buffer
  132.                cSendFrame(&xSendData);
  133.             }
  134.             while (br == SIZEOFBUFFER);
  135.          }
  136.  
  137.          vAudioFileDemo_close:
  138.          f_close(&audioFile);
  139.       }      
  140.  
  141.       vAudioFileDemo_umount:
  142.       // Unregister a work area before discard it
  143.       f_mount(0, NULL);
  144.        
  145.       vAudioFileDemo_finish:  
  146.       vTaskDelete(xAudioFileDemoHandle);
  147.    }
  148. }
  149.  
  150. static void prvSetupHardware( void )
  151. {
  152.     /* When using the JTAG debugger the hardware is not always initialised to
  153.     the correct default state.  This line just ensures that this does not
  154.     cause all interrupts to be masked at the start. */
  155.     AT91C_BASE_AIC->AIC_EOICR = 0;
  156.    
  157.     /* Enable the peripheral clock to the PIO */
  158.     AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_PIOA);
  159. }

Link al codigo src en zip
El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Re: Player de archivos WAV en AT91SAM7S con FreeRTOS
« Respuesta #8 en: 06 de Noviembre de 2009, 01:16:49 »
Super interesante el proyecto!! Que DAC I2S utilizaste? Porque estaba viendo el de National Semiconductor y es imposible soldarlo  :8}

Felicitaciones!!
Use el HT82V731 de Holtek, que es un clon chino pin a pin del TDA1311, el cual es re simple ya que es un SOIC 8 con minimos componentes. En este este thread de sistemasembebidos estamos haciendo un poll para comprar el WM8762 que es algo muy parecido (la unica diferencia es que requiere MCK).

En mouser.com comprando 50 unidades sale 1.33 dolares (faltan gastos de envio e impuestos usur-nacionalizables), si juntamos al menos 8 serian 6 chips per capita y la verdad no es mucha plata.

El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/