/******************************************************************************/ /* Speicher, Laden und Erzeugen von WAV und PCM Dateien /* /* Datum : 27.03.2002 /* Autor : Jens Ahrensfeld /* Datei : wav.c /* /******************************************************************************/ #include "stdio.h" #include "stdlib.h" #include "string.h" #include "wav.h" /******************************************************************************/ /* C definitions /******************************************************************************/ void WavInit(struct _sWAV *pObj, UINT32 nSamplesPerSec, UINT16 nBits, UINT16 nChannels, UINT16 format) { WavSetFormat(pObj, nSamplesPerSec, nBits, nChannels, format); pObj->m_FileType = FILETYPE_RAW; pObj->m_FileSize = 0; pObj->m_HeaderSize = 0; pObj->m_DataSize = 0; pObj->pHndWavFile = 0; pObj->m_numSamples = 0; } /******************************************************************************/ UINT32 WavSetFormat(struct _sWAV *pObj, UINT32 nSamplesPerSec, UINT16 nBits, UINT16 nChannels, UINT16 format) { pObj->m_Format.wFormatTag = format; pObj->m_Format.nChannels = nChannels; pObj->m_Format.wBitsPerSample = nBits; pObj->m_Format.nBlockAlign = (nChannels * nBits)/ 8; pObj->m_Format.nSamplesPerSec = nSamplesPerSec; pObj->m_Format.nAvgBytesPerSec = (UINT32)pObj->m_Format.nBlockAlign * nSamplesPerSec; pObj->m_Format.cbSize = 0; pObj->m_nChannels = pObj->m_Format.nChannels; pObj->m_SampleRate = pObj->m_Format.nSamplesPerSec; pObj->m_nBits = pObj->m_Format.wBitsPerSample; return 0; } /******************************************************************************/ UINT32 WavOpen (struct _sWAV *pObj, char* FileName) { UINT32 stat; //Wav-File öffnen strcpy(pObj->m_Name, FileName); if (strlen(FileName) < 1) return -1; pObj->pHndWavFile = fopen (pObj->m_Name,"rb"); if (pObj->pHndWavFile == 0) return -1; stat=ReadHeader(pObj); if (stat != 0) { pObj->m_FileType = FILETYPE_RAW; fseek(pObj->pHndWavFile, 0L, SEEK_END); pObj->m_DataSize = ftell(pObj->pHndWavFile); pObj->m_FileSize = pObj->m_DataSize; pObj->m_numSamples = pObj->m_DataSize/pObj->m_Format.nBlockAlign; fseek(pObj->pHndWavFile, 0L, SEEK_SET); pObj->WREAD = 1; return 0; } pObj->m_numSamples = pObj->m_DataSize /pObj->m_Format.nBlockAlign; pObj->m_FileType = FILETYPE_WAV; pObj->WREAD = 1; return 0; } /******************************************************************************/ UINT32 WavClose(struct _sWAV *pObj) { if (!pObj->WREAD && (pObj->m_FileType == FILETYPE_WAV)) WriteHeader(pObj); fclose(pObj->pHndWavFile); return 0; } /******************************************************************************/ UINT32 WavCreate (struct _sWAV *pObj, char *fileName, UINT32 fileType) { pObj->m_FileType = fileType; strcpy(pObj->m_Name, fileName); //Wav-File öffnen pObj->pHndWavFile = fopen (pObj->m_Name,"wb"); if (pObj->pHndWavFile == 0) return -1; pObj->WREAD = 0; if (pObj->m_FileType == FILETYPE_WAV) WriteHeader(pObj); return 0; } /******************************************************************************/ UINT32 WavRead(struct _sWAV *pObj, void *data, UINT32 nSamples) { INT32 count; count = fread(data, pObj->m_Format.nBlockAlign, nSamples, pObj->pHndWavFile); return count; } /******************************************************************************/ UINT32 WavWrite(struct _sWAV *pObj, void *data, UINT32 nSamples) { UINT32 count; fseek(pObj->pHndWavFile, 0L, SEEK_END); count = fwrite(data, pObj->m_Format.nBlockAlign, nSamples, pObj->pHndWavFile); pObj->m_DataSize = pObj->m_DataSize + count*pObj->m_Format.nBlockAlign; pObj->m_numSamples = count; pObj->m_FileSize = pObj->m_DataSize; if (pObj->m_FileType == FILETYPE_WAV) pObj->m_FileSize += pObj->m_HeaderSize + 20; return count; } /******************************************************************************/ UINT32 ReadHeader (struct _sWAV *pObj) { char buf[80]; INT32 err; // 1. 'RIFF' abprüfen fread(buf, sizeof(char), 4,pObj->pHndWavFile); buf[4]=0; if (strcmp (buf,"RIFF")) return -1; // 2. FILESIZE ermitteln fread(&pObj->m_FileSize, sizeof(UINT32), 1,pObj->pHndWavFile); // 3. 'WAVEfmt' abprüfen fread(buf, sizeof(char), 8,pObj->pHndWavFile); buf[8]=0; if (strcmp (buf,"WAVEfmt ")) return -1; // 3. HeaderSize ermitteln fread(&pObj->m_HeaderSize, sizeof(pObj->m_HeaderSize), 1,pObj->pHndWavFile); // 4. Den ganzen Infoblock einlesen fread(&pObj->m_Format, pObj->m_HeaderSize, 1,pObj->pHndWavFile); // 5. 'data' abprüfen fseek(pObj->pHndWavFile,(INT32)(pObj->m_HeaderSize+20), SEEK_SET); err = -1; do { fread(buf, sizeof(char), 4, pObj->pHndWavFile); buf[4]=0; // 6. Datenlänge ermitteln fread(&pObj->m_DataSize, sizeof(pObj->m_DataSize), 1,pObj->pHndWavFile); if (!strcmp (buf,"data")) { err = 0; break; } fseek(pObj->pHndWavFile,(INT32)(pObj->m_DataSize), SEEK_CUR); } while (!feof(pObj->pHndWavFile)); pObj->m_nChannels = pObj->m_Format.nChannels; pObj->m_SampleRate = pObj->m_Format.nSamplesPerSec; pObj->m_nBits = pObj->m_Format.wBitsPerSample; return err; } /******************************************************************************/ UINT32 WriteHeader (struct _sWAV *pObj) { pObj->m_HeaderSize = bs; pObj->m_FileSize = pObj->m_HeaderSize + pObj->m_DataSize + 20; fseek(pObj->pHndWavFile,0L, SEEK_SET); // 1. 'RIFF' schreiben fwrite("RIFF",sizeof(char), 4, pObj->pHndWavFile); // 2. FILESIZE schreiben fwrite(&pObj->m_FileSize, sizeof(pObj->m_FileSize), 1, pObj->pHndWavFile); // 3. 'WAVEfmt ' schreiben fwrite("WAVEfmt ", sizeof(char), 8, pObj->pHndWavFile); // 3. HeaderSize schreiben fwrite(&pObj->m_HeaderSize, sizeof(pObj->m_HeaderSize), 1, pObj->pHndWavFile); // 4. Infoblock schreiben fwrite(&pObj->m_Format, pObj->m_HeaderSize, 1, pObj->pHndWavFile); // 5. 'data' schreiben fseek(pObj->pHndWavFile, (INT32)(pObj->m_HeaderSize+20), SEEK_SET); fwrite("data",sizeof(char), 4, pObj->pHndWavFile); // 6. Datenlänge schreiben fwrite(&pObj->m_DataSize, sizeof(pObj->m_DataSize), 1, pObj->pHndWavFile); return 0; } /******************************************************************************/ UINT16 WavGetnBits(struct _sWAV *pObj) { return pObj->m_Format.wBitsPerSample; } UINT32 WavGetRate(struct _sWAV *pObj) { return pObj->m_Format.nSamplesPerSec; } UINT16 WavGetnChannels(struct _sWAV *pObj) { return pObj->m_Format.nChannels; } char* WavGetFileName(struct _sWAV *pObj) { return pObj->m_Name; } void WavDeIlvd(struct _sWAV *pObj, INT16 *pIn, INT16 **ppOut, UINT32 len) { int j, nChannels; UINT32 i; nChannels = pObj->m_Format.nChannels; for (i=0; i < len; i++) { for (j=0; j < nChannels; j++) { ppOut[j][i] = *(pIn++); } } } void WavDeIlvdDouble(struct _sWAV *pObj, INT16 *pIn, double **ppOut, UINT32 len) { int j, nChannels, nBits; UINT32 i; double kNorm; nChannels = pObj->m_Format.nChannels; nBits = pObj->m_Format.wBitsPerSample; kNorm = 1.0/((1 << (nBits-1))-1); for (i=0; i < len; i++) { for (j=0; j < nChannels; j++) { ppOut[j][i] = (double)(*(pIn++) * kNorm); } } } void WavDeIlvdFloat(struct _sWAV *pObj, INT16 *pIn, float **ppOut, UINT32 len) { int j, nChannels, nBits; UINT32 i; float kNorm; nChannels = pObj->m_Format.nChannels; nBits = pObj->m_Format.wBitsPerSample; kNorm = 1.0f/((1 << (nBits-1))-1); for (i=0; i < len; i++) { for (j=0; j < nChannels; j++) { ppOut[j][i] = (float)(*(pIn++) * kNorm); } } } void WavIlvd(struct _sWAV *pObj, INT16 **ppIn, INT16 *pOut, UINT32 len) { int j, nChannels; UINT32 i; nChannels = pObj->m_Format.nChannels; for (i=0; i < len; i++) { for (j=0; j < nChannels; j++) { *(pOut++) = ppIn[j][i]; } } } void WavIlvdDouble(struct _sWAV *pObj, double **ppIn, INT16 *pOut, UINT32 len) { int j, nChannels, nBits; double kNorm; UINT32 i; nChannels = pObj->m_Format.nChannels; nBits = pObj->m_Format.wBitsPerSample; kNorm = (1 << (nBits-1))-1; for (i=0; i < len; i++) { for (j=0; j < nChannels; j++) { *(pOut++) = (INT16)(ppIn[j][i] * kNorm); } } } void WavIlvdFloat(struct _sWAV *pObj, float **ppIn, INT16 *pOut, UINT32 len) { int j, nChannels, nBits; float kNorm; UINT32 i; nChannels = pObj->m_Format.nChannels; nBits = pObj->m_Format.wBitsPerSample; kNorm = (float)(1 << (nBits-1))-1; for (i=0; i < len; i++) { for (j=0; j < nChannels; j++) { *(pOut++) = (INT16)(ppIn[j][i] * kNorm); } } }