This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Wave Player

Other Parts Discussed in Thread: TM4C1231H6PZ

Sir , 

I am reading wave files from a microSD card using TIVA TM4C1231H6PZ . The problem is file is not opening.

The code is: 

#include <string.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/flash.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"
#include "driverlib/systick.h"
#include "utils/ustdlib.h"
#include "driverlib/ff.h"
#include "driverlib/diskio.h"
#include "utils/uartstdio.h"
#include "driverlib/LCD_TIVA.h"

#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

//******************************************************************************
//
//! \addtogroup example_list
//! <h1>I2S example application using SD Card FAT file system (i2s_demo)</h1>
//!
//! This example application demonstrates playing wav files from an SD card that
//! is formatted with a FAT file system. The application will only look in the
//! root directory of the SD card and display all files that are found. Files
//! can be selected to show their format and then played if the application
//! determines that they are a valid .wav file. Only PCM format (uncompressed)
//! files may be played.
//!
//! For additional details about FatFs, see the following site:
//! http://elm-chan.org/fsw/ff/00index_e.html
//
//******************************************************************************

//******************************************************************************
//
// The following are data structures used by FatFs.
//
//******************************************************************************
static FATFS g_sFatFs;
static DIR g_sDirObject;
static FILINFO g_sFileInfo;
static FIL g_sFileObject;

//******************************************************************************
//
// The number of SysTick ticks per second.
//
//******************************************************************************
#define TICKS_PER_SECOND 100

//******************************************************************************
//
// Storage for the filename listbox widget string table.
//
//******************************************************************************
#define NUM_LIST_STRINGS 48
const char *g_ppcDirListStrings[NUM_LIST_STRINGS];

//******************************************************************************
//
// Storage for the names of the files in the current directory. Filenames
// are stored in format "filename.ext".
//
//******************************************************************************
#define MAX_FILENAME_STRING_LEN (8 + 1 + 3 + 1)
char g_pcFilenames[NUM_LIST_STRINGS][MAX_FILENAME_STRING_LEN];


//******************************************************************************
//
// Buffer management and flags.
//
//******************************************************************************
#define AUDIO_BUFFER_SIZE 4096
static unsigned char g_pucBuffer[AUDIO_BUFFER_SIZE];
unsigned long g_ulMaxBufferSize;

//
// Flags used in the g_ulFlags global variable.
//
#define BUFFER_BOTTOM_EMPTY 0x00000001
#define BUFFER_TOP_EMPTY 0x00000002
#define BUFFER_PLAYING 0x00000004
static volatile unsigned long g_ulFlags;

//
// Globals used to track playback position.
//
static unsigned long g_ulBytesRemaining;
static unsigned short g_usMinutes;
static unsigned short g_usSeconds;

//******************************************************************************
//
// Handler for buffers being released.
//
//******************************************************************************


//******************************************************************************
//
// Basic wav file RIFF header information used to open and read a wav file.
//
//******************************************************************************
#define RIFF_CHUNK_ID_RIFF 0x46464952
#define RIFF_CHUNK_ID_FMT 0x20746d66
#define RIFF_CHUNK_ID_DATA 0x61746164

#define RIFF_TAG_WAVE 0x45564157

#define RIFF_FORMAT_UNKNOWN 0x0000
#define RIFF_FORMAT_PCM 0x0001
#define RIFF_FORMAT_MSADPCM 0x0002
#define RIFF_FORMAT_IMAADPCM 0x0011

//******************************************************************************
//
// The wav file header information.
//
//******************************************************************************

void SysTickHandler(void)
{
SysTickIntDisable();
disk_timerproc();
SysTickIntEnable();
}


void InitConsole(void)
{
/* Enable GPIO port A which is used for UART0 pins. */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

/* Make the UART pins be peripheral controlled. */
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

/* Initialize the UART for console I/O. */
UARTStdioInit(0);
UARTprintf("HELLO\n");
}

typedef struct
{
//
// Sample rate in bytes per second.
//
unsigned long ulSampleRate;

//
// The average byte rate for the wav file.
//
unsigned long ulAvgByteRate;

//
// The size of the wav data in the file.
//
unsigned long ulDataSize;

//
// The number of bits per sample.
//
unsigned short usBitsPerSample;

//
// The wav file format.
//
unsigned short usFormat;

//
// The number of audio channels.
//
unsigned short usNumChannels;
}
tWaveHeader;
static tWaveHeader g_sWaveHeader;

//******************************************************************************
//
// This function can be used to test if a file is a wav file or not and will
// also return the wav file header information in the pWaveHeader structure.
// If the file is a wav file then the psFileObject pointer will contain an
// open file pointer to the wave file ready to be passed into the WavePlay()
// function.
//
//******************************************************************************

FRESULT
WaveOpen(FIL *psFileObject, const char *pcFileName, tWaveHeader *pWaveHeader)
{
unsigned long *pulBuffer;
unsigned short *pusBuffer;
unsigned long ulChunkSize;
unsigned short usCount;
unsigned long ulBytesPerSample;
FRESULT Result;
LCDInitialize();
pulBuffer = (unsigned long *)g_pucBuffer;
pusBuffer = (unsigned short *)g_pucBuffer;

Result = f_open(psFileObject, pcFileName,FA_READ);
if(Result != FR_OK)
{
LCDWriteString("ERROR Opening!!!");
GPIOPinWrite(GPIO_PORTC_BASE,GPIO_PIN_7,GPIO_PIN_7);
return(Result);
}

//
// Read the first 12 bytes.
//
Result = f_read(psFileObject, g_pucBuffer, 12, &usCount);
if(Result != FR_OK)
{
LCDWriteString("ERROR Reading!!!");
f_close(psFileObject);
return(Result);
}


LCDWriteString("Byte 1:");
// UARTprintf("Byte 2: %d\n",g_pucBuffer[1]);
// UARTprintf("Byte 3: %d\n",g_pucBuffer[2]);
// UARTprintf("byte 4: %d\n",g_pucBuffer[3]);
// UARTprintf("byte 5: %d\n",g_pucBuffer[4]);
// UARTprintf("byte 6: %d\n",g_pucBuffer[5]);
// UARTprintf("byte 7: %d\n",g_pucBuffer[6]);
// UARTprintf("byte 14: %d\n",g_pucBuffer[14]);
//
// Look for RIFF tag.
//
if((pulBuffer[0] != RIFF_CHUNK_ID_RIFF) || (pulBuffer[2] != RIFF_TAG_WAVE))
{
LCDWriteString("could not read RIF ");
f_close(psFileObject);
return(FR_INVALID_NAME);
}

//
// Read the next chunk header.
//
Result = f_read(psFileObject, g_pucBuffer, 8, &usCount);
if(Result != FR_OK)
{
f_close(psFileObject);
return(Result);
}
//UARTprintf("9.Result=%d\n",Result);
if(pulBuffer[0] != RIFF_CHUNK_ID_FMT)
{
f_close(psFileObject);
return(FR_INVALID_NAME);
}

//
// Read the format chunk size.
//

ulChunkSize = pulBuffer[1];

if(ulChunkSize > 16)
{
f_close(psFileObject);
return(FR_INVALID_NAME);
}

//
// Read the next chunk header.
//
Result = f_read(psFileObject, g_pucBuffer, ulChunkSize, &usCount);
if(Result != FR_OK)
{

f_close(psFileObject);
return(Result);
}
LCDWriteString("10.Result=");

pWaveHeader->usFormat = pusBuffer[0];
pWaveHeader->usNumChannels = pusBuffer[1];
pWaveHeader->ulSampleRate = pulBuffer[1];
pWaveHeader->ulAvgByteRate = pulBuffer[2];
pWaveHeader->usBitsPerSample = pusBuffer[7];

//
// Reset the byte count.
//
//g_ulBytesPlayed = 0;
//g_ulNextUpdate = 0;

//
// Calculate the Maximum buffer size based on format. There can only be
// 1024 samples per ping pong buffer due to uDMA.
//
ulBytesPerSample = (pWaveHeader->usBitsPerSample *
pWaveHeader->usNumChannels) >> 3;

if(((AUDIO_BUFFER_SIZE >> 1) / ulBytesPerSample) > 1024)
{
//
// The maximum number of DMA transfers was more than 1024 so limit
// it to 1024 transfers.
//
g_ulMaxBufferSize = 1024 * ulBytesPerSample;
}
else
{
//
// The maximum number of DMA transfers was not more than 1024.
//
g_ulMaxBufferSize = AUDIO_BUFFER_SIZE >> 1;
}

//
// Only mono and stereo supported.
//
if(pWaveHeader->usNumChannels > 2)
{
f_close(psFileObject);
return(FR_INVALID_NAME);
}

//
// Read the next chunk header.
//
Result = f_read(psFileObject, g_pucBuffer, 8, &usCount);
if(Result != FR_OK)
{
f_close(psFileObject);
return(Result);
}
//UARTprintf("g_pucBuffer%d\n",g_pucBuffer);


if(pulBuffer[0] != RIFF_CHUNK_ID_DATA)
{
f_close(psFileObject);
return(Result);
}

//
// Save the size of the data.
//
pWaveHeader->ulDataSize = pulBuffer[1];
LCDWriteString("11.pulBuffer[1]=");

g_usSeconds = pWaveHeader->ulDataSize/pWaveHeader->ulAvgByteRate;
g_usMinutes = g_usSeconds/60;
g_usSeconds -= g_usMinutes*60;
LCDWriteString("12.g_usMinutes=");
LCDWriteString("13.g_usSeconds=");

//
// Set the number of data bytes in the file.
//
g_ulBytesRemaining = pWaveHeader->ulDataSize;
LCDWriteString("I came here");
//
// Adjust the average bit rate for 8 bit mono files.
//
if((pWaveHeader->usNumChannels == 1) && (pWaveHeader->usBitsPerSample == 8))
{
pWaveHeader->ulAvgByteRate <<=1;
}

//
// Set the format of the playback in the sound driver.
//


return(FR_OK);
}

//******************************************************************************
//
// This closes out the wav file.
//
//******************************************************************************
void
WaveClose(FIL *psFileObject)
{
//
// Close out the file.
//

LCDWriteString("I closed file");
f_close(psFileObject);
}

//******************************************************************************
//
// Convert an 8 bit unsigned buffer to 8 bit signed buffer in place so that it
// can be passed into the i2s playback.
//
//******************************************************************************
void
Convert8Bit(unsigned char *pucBuffer, unsigned long ulSize)
{
unsigned long ulIdx;

for(ulIdx = 0; ulIdx < ulSize; ulIdx++)
{
//
// In place conversion of 8 bit unsigned to 8 bit signed.
//
*pucBuffer = ((short)(*pucBuffer)) - 128;
pucBuffer++;
}
}

//******************************************************************************
//
// This function is used to tell when to update the playback times for a file.
// It will only update the screen at 1 second intervals but can be called more
// often with no result.
//
//******************************************************************************

//******************************************************************************
//
// This function is used to update the file information area of the screen.
//
//******************************************************************************
void
UpdateFileInfo(void)
{
short sSelected;

//
// Get the current selection from the list box.
//
// sSelected = ListBoxSelectionGet(&g_sDirList);

//
// Just return if nothing is currently selected.
//
if(sSelected == -1)
{
//
// Set the time and format strings to null strings.
//
// g_pcTime[0] = 0;
// g_pcFormat[0] = 0;
}
//
// If this is successful then the file passed in was a wav file.
//
else if(dd(&g_sFileObject, g_pcFilenames[sSelected], &g_sWaveHeader) == FR_OK)
{

//
// Update the file name information.
//
//strncpy(g_pcFileName, g_pcFilenames[sSelected], 16);

//
// Print the formatted string so that it can be displayed.
//
//usprintf(g_pcFormat, "%d Hz %d bit ", g_sWaveHeader.ulSampleRate,
// g_sWaveHeader.usBitsPerSample);

//
// Concatenate the number of channels.
//
if(g_sWaveHeader.usNumChannels == 1)
{
// strcat(g_pcFormat, "Mono");
}
else
{
//strcat(g_pcFormat, "Stereo");
}

//
// Close the file, it will be reopend on play.
//
f_close(&g_sFileObject);

//
// Update the real display time.
//
//DisplayTime(0);
}
else
{
//
// Update the file name information.
//
//strncpy(g_pcFileName, g_pcFilenames[sSelected], 16);

//
// Set the time and format strings to null strings.
//
// g_pcTime[0] = 0;
// g_pcFormat[0] = 0;
}

//
// Update all to the files information on the screen.
//
}

//******************************************************************************
//
// This function will handle stopping the playback of audio. It will not do
// this immediately but will defer stopping audio at a later time. This allows
// this function to be called from an interrupt handler.
//
//******************************************************************************
void
WaveStop(void)
{
//
// Stop playing audio.
//
g_ulFlags &= ~BUFFER_PLAYING;
}

//******************************************************************************
//
// This function will handle reading the correct amount from the wav file and
// will also handle converting 8 bit unsigned to 8 bit signed if necessary.
//
//******************************************************************************
unsigned short
WaveRead(FIL *psFileObject, tWaveHeader *pWaveHeader, unsigned char *pucBuffer)
{
unsigned long ulBytesToRead;
unsigned short usCount;

//
// Either read a half buffer or just the bytes remaining if we are at the
// end of the file.
//
if(g_ulBytesRemaining < g_ulMaxBufferSize)
{
ulBytesToRead = g_ulBytesRemaining;
}
else
{
ulBytesToRead = g_ulMaxBufferSize;
}

//
// Read in another buffer from the sd card.
//
if(f_read(&g_sFileObject, pucBuffer, ulBytesToRead, &usCount) != FR_OK)
{
return(0);
}

//
// Decrement the number of data bytes remaining to be read.
//
g_ulBytesRemaining -= usCount;

//
// Need to convert the audio from unsigned to signed if 8 bit
// audio is used.
//
if(pWaveHeader->usBitsPerSample == 8)
{
Convert8Bit(pucBuffer, usCount);
}

return(usCount);

}

//******************************************************************************
//
// This will play the file passed in via the psFileObject parameter based on
// the format passed in the pWaveHeader structure. The WaveOpen() function
// can be used to properly fill the pWaveHeader and psFileObject structures.
//
//******************************************************************************
unsigned long
WavePlay(FIL *psFileObject, tWaveHeader *pWaveHeader)
{
static unsigned short usCount;

//
// Mark both buffers as empty.
//
g_ulFlags = BUFFER_BOTTOM_EMPTY | BUFFER_TOP_EMPTY;

//
// Indicate that the application is about to start playing.
//
g_ulFlags |= BUFFER_PLAYING;

while(1)
{
//
// Must disable I2S interrupts during this time to prevent state
// problems.
//IntDisable(INT_I2S0);
// If the refill flag gets cleared then fill the requested side of the
// buffer.
if(g_ulFlags & BUFFER_BOTTOM_EMPTY)
{
//
// Read out the next buffer worth of data.
//
usCount = WaveRead(psFileObject, pWaveHeader, g_pucBuffer);
LCDWriteString("I read something");
//
// Start the playback for a new buffer.
//
//SoundBufferPlay(g_pucBuffer, usCount, BufferCallback);

//
// Bottom half of the buffer is now not empty.
//
g_ulFlags &= ~BUFFER_BOTTOM_EMPTY;
}

if(g_ulFlags & BUFFER_TOP_EMPTY)
{
//
// Read out the next buffer worth of data.
//
usCount = WaveRead(psFileObject, pWaveHeader,
&g_pucBuffer[AUDIO_BUFFER_SIZE >> 1]);

//
// Start the playback for a new buffer.
//
// SoundBufferPlay(&g_pucBuffer[AUDIO_BUFFER_SIZE >> 1],
// usCount, BufferCallback);

//
// Top half of the buffer is now not empty.
//
g_ulFlags &= ~BUFFER_TOP_EMPTY;

}

//
// If something reset this while playing then stop playing and break
// out of the loop.
//

}

//
// Audio playback is done once the count is below a full buffer.
//
if((usCount < g_ulMaxBufferSize) || (g_ulBytesRemaining == 0))
{

//
// No longer playing audio.
//
LCDWriteString("Played once!");
g_ulFlags &= ~BUFFER_PLAYING;

//
// Wait for the buffer to empty.
//
while(g_ulFlags != (BUFFER_TOP_EMPTY | BUFFER_BOTTOM_EMPTY))
{
}

// break;
}

//
// Must disable I2S interrupts during this time to prevent state
// problems.
//

//
// Close out the file.
//
WaveClose(psFileObject);

return(0);
}


//******************************************************************************
//
// This is the handler for this SysTick interrupt. FatFs requires a
// timer tick every 10 ms for internal timing purposes.
//
//******************************************************************************


//******************************************************************************
//
// This function is called to read the contents of the current directory on
// the SD card and fill the listbox containing the names of all files.
//
//******************************************************************************


//******************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//******************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

//******************************************************************************
//
// The program main function. It performs initialization, then handles wav
// file playback.
//
//******************************************************************************
int
main(void)
{

/*Set the clocking to run at 20Mhz from the crystal of 8MHz using PLL*/
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);


SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
// SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE,GPIO_PIN_7);
InitConsole();
/*Configure SysTick for a 100Hz interrupt. The FatFs driver wants a 10 milliseconds interrupt.*/
SysTickPeriodSet(SysCtlClockGet() / 100);
SysTickIntRegister(SysTickHandler);
SysTickEnable();
SysTickIntEnable();
/*Enable global interupts*/
IntMasterEnable();

LCDInitialize();
LCDDisplayInitializing();

FRESULT fresult;


LCDWriteString("MOUNT initialize!!!");


fresult = f_mount(0, &g_sFatFs);
if(fresult != FR_OK)
{

LCDWriteString("Error Mount!");
}

//
// Not playing anything right now.
//
g_ulFlags = 0;

//
//
//SoundInit(0);
while(1)
{
if(WaveOpen(&g_sFileObject,"abc.wav",&g_sWaveHeader) == FR_OK)
{
LCDWriteString("I m OK in opening ");
}


WavePlay(&g_sFileObject, &g_sWaveHeader);
}
}

Kindly point out mistakes and suggest ways to solve them.

I would be very grateful.