📄 msadpcm.c
字号:
{ lSamp = -32768; } // // compute the next iDelta // sDelta = (short)((psP4[sOutput & 15] * (long)sDelta) >> MSADPCM_PSCALE); if(sDelta < MSADPCM_DELTA4_MIN) { sDelta = MSADPCM_DELTA4_MIN; } // // save updated values for this channel back into the // original arrays... // psDelta[ucChannel] = sDelta; psSamp2[ucChannel] = psSamp1[ucChannel]; psSamp1[ucChannel] = (short)lSamp; // // we have another nibble of encoded data--either combine // this with the previous nibble and write out a full // byte, or save this nibble for the next nibble to be // combined into a full byte and written to the destination // buffer... uhg! // if(ucFirstNibble) { ucNextWrite = (sOutput & 15) << 4; ucFirstNibble = 0; } else { *pucDst++ = ucNextWrite | (sOutput & 15); ulTotalConverted++; ucFirstNibble = 1; } } } // // return the number of bytes in the encoded ADPCM block // return (ulTotalConverted);}//****************************************************************************//// MSADPCMSetupDecoder prepares to decode a file using the MS ADPCM decoder.////****************************************************************************unsigned longMSADPCMSetupDecoder(tMSADPCM *pMSADPCM){ ADPCMWaveFormat sWaveFormat; unsigned long ulOffset, ulLength; // // Seek to the beginning of the file. // FSSeek(pMSADPCM->pFile, 0); // // Read the first portion of the file. // pMSADPCM->usValid = FSRead(pMSADPCM->pFile, pMSADPCM->pucEncodedData, 4096); // // Make sure that this is a RIFF WAVE file. // if((pMSADPCM->usValid < 12) || (pMSADPCM->pucEncodedData[0] != 'R') || (pMSADPCM->pucEncodedData[1] != 'I') || (pMSADPCM->pucEncodedData[2] != 'F') || (pMSADPCM->pucEncodedData[3] != 'F') || (pMSADPCM->pucEncodedData[8] != 'W') || (pMSADPCM->pucEncodedData[9] != 'A') || (pMSADPCM->pucEncodedData[10] != 'V') || (pMSADPCM->pucEncodedData[11] != 'E')) { return(0); } // // Find the "fmt " chunk. // ulOffset = CodecFindRIFFChunk(pMSADPCM->pucEncodedData, pMSADPCM->usValid, 12, "fmt "); if(ulOffset == -1) { return(0); } // // Get the length of the "fmt " chunk. // ulLength = ((pMSADPCM->pucEncodedData[ulOffset + 7] << 24) | (pMSADPCM->pucEncodedData[ulOffset + 6] << 16) | (pMSADPCM->pucEncodedData[ulOffset + 5] << 8) | pMSADPCM->pucEncodedData[ulOffset + 4]); // // If the length of the "fmt " chunk is not the same as the size of the MS // ADPCM wave format sturcture, then we can not decode this file. // if(ulLength != sizeof(ADPCMWaveFormat)) { return(0); } // // Make sure that the entire "fmt " chunk is in the data buffer. // if((ulOffset + ulLength + 8) > pMSADPCM->usValid) { return(0); } // // Copy the wave format structure from the "fmt " chunk into a/ local. We // do this instead of grabbing the values directly from the data buffer // since the "fmt " chunk can occur with any alignment, making it a lot // easier to simply copy the structure. // memcpy((void *)&sWaveFormat, pMSADPCM->pucEncodedData + ulOffset + 8, sizeof(ADPCMWaveFormat)); // // Perform some sanity checks on the wave format structure. // if((sWaveFormat.wFormatTag != 2) || (sWaveFormat.nChannels > 2) || (sWaveFormat.nSamplesPerSec > 48000) || (sWaveFormat.nBlockAlign > 4096) || (sWaveFormat.wBitsPerSample != 4) || (sWaveFormat.cbSize != 32) || (sWaveFormat.wSamplesPerBlock > MSADPCM_MAX_PCM_LENGTH) || (sWaveFormat.wNumCoef != 7)) { // // The wave format does not pass the sanity checks, so we can not // decode this file. // return(0); } // // Make sure that the coefficients match the MS ADPCM coefficients. // for(ulLength = 0; ulLength < 7; ulLength++) { if((sWaveFormat.aCoef[ulLength].iCoef1 != psCoefficient1[ulLength]) || (sWaveFormat.aCoef[ulLength].iCoef2 != psCoefficient2[ulLength])) { // // The coefficients do not match the MS ADPCM coefficients, so we // can not decode this file. // return(0); } } // // Save information about this file which we will need. // pMSADPCM->usSampleRate = sWaveFormat.nSamplesPerSec; pMSADPCM->ucChannels = sWaveFormat.nChannels; pMSADPCM->usBytesPerBlock = sWaveFormat.nBlockAlign; pMSADPCM->usSamplesPerBlock = sWaveFormat.wSamplesPerBlock; // // Compute the byte rate as the header is often inaccurate (thanks // Microsoft). // pMSADPCM->ulBitRate = ((sWaveFormat.nSamplesPerSec * 8 * sWaveFormat.nBlockAlign) / sWaveFormat.wSamplesPerBlock); // // Find the "data" chunk. // ulOffset = CodecFindRIFFChunk(pMSADPCM->pucEncodedData, pMSADPCM->usValid, 12, "data"); if(ulOffset == -1) { return(0); } // // Save the starting position of the "data" chunk. // pMSADPCM->ulDataStart = ulOffset + 8; // // Get the length of the "data" chunk. // pMSADPCM->ulLength = ((pMSADPCM->pucEncodedData[ulOffset + 7] << 24) | (pMSADPCM->pucEncodedData[ulOffset + 6] << 16) | (pMSADPCM->pucEncodedData[ulOffset + 5] << 8) | pMSADPCM->pucEncodedData[ulOffset + 4]); // // Advance to the current buffer offset to the first byte of the "data" // chunk. // pMSADPCM->usOffset = ulOffset + 8; // // Compute the time length of the file. We ignore the "fact" chunk in the // file since Microsoft's Sound Recorder on the PC (for example) does not // put the correct value into this chunk (it over-states the number of // samples in the file). // pMSADPCM->ulTimeLength = ((((pMSADPCM->ulLength * 8) / pMSADPCM->ulBitRate) * 1000) + ((((pMSADPCM->ulLength * 8) % pMSADPCM->ulBitRate) * 1000) / pMSADPCM->ulBitRate)); // // The position is zero. // pMSADPCM->ulTimePos = 0; // // Initially, all the data in the file is valid. // pMSADPCM->ulDataValid = pMSADPCM->ulLength + pMSADPCM->usOffset; // // There is no output buffer. // pMSADPCM->pBuffer = 0; // // Success. // return(1);}//****************************************************************************//// MSADPCMSetupEncoder prepares to encode a file using the MS ADPCM encoder.////****************************************************************************unsigned longMSADPCMSetupEncoder(tMSADPCM *pMSADPCM){ ADPCMWaveFormat sWaveFormat; unsigned long ulIdx; // // We encode files at 8kHz, mono. So, the following parameters are fixed. // pMSADPCM->ulBitRate = 32768; pMSADPCM->usSampleRate = 8000; pMSADPCM->ucChannels = 1; pMSADPCM->usBytesPerBlock = 256; pMSADPCM->usSamplesPerBlock = 500; // // Build the RIFF header in the encoded data buffer. // pMSADPCM->pucEncodedData[0] = 'R'; pMSADPCM->pucEncodedData[1] = 'I'; pMSADPCM->pucEncodedData[2] = 'F'; pMSADPCM->pucEncodedData[3] = 'F'; pMSADPCM->pucEncodedData[4] = 0; pMSADPCM->pucEncodedData[5] = 0; pMSADPCM->pucEncodedData[6] = 0; pMSADPCM->pucEncodedData[7] = 0; pMSADPCM->pucEncodedData[8] = 'W'; pMSADPCM->pucEncodedData[9] = 'A'; pMSADPCM->pucEncodedData[10] = 'V'; pMSADPCM->pucEncodedData[11] = 'E'; // // Fill in the wave format structure. // sWaveFormat.wFormatTag = 2; sWaveFormat.nChannels = pMSADPCM->ucChannels; sWaveFormat.nSamplesPerSec = pMSADPCM->usSampleRate; sWaveFormat.nAvgBytesPerSec = pMSADPCM->ulBitRate / 8; sWaveFormat.nBlockAlign = pMSADPCM->usBytesPerBlock; sWaveFormat.wBitsPerSample = 4; sWaveFormat.cbSize = 32; sWaveFormat.wSamplesPerBlock = pMSADPCM->usSamplesPerBlock; sWaveFormat.wNumCoef = 7; for(ulIdx = 0; ulIdx < 7; ulIdx++) { sWaveFormat.aCoef[ulIdx].iCoef1 = psCoefficient1[ulIdx]; sWaveFormat.aCoef[ulIdx].iCoef2 = psCoefficient2[ulIdx]; } // // Add the "fmt " chunk in the encoded data buffer. // pMSADPCM->pucEncodedData[12] = 'f'; pMSADPCM->pucEncodedData[13] = 'm'; pMSADPCM->pucEncodedData[14] = 't'; pMSADPCM->pucEncodedData[15] = ' '; pMSADPCM->pucEncodedData[16] = 50; pMSADPCM->pucEncodedData[17] = 0; pMSADPCM->pucEncodedData[18] = 0; pMSADPCM->pucEncodedData[19] = 0; memcpy(pMSADPCM->pucEncodedData + 20, (void *)&sWaveFormat, 50); // // Add the "fact" chunk in the encoded data buffer. // pMSADPCM->pucEncodedData[70] = 'f'; pMSADPCM->pucEncodedData[71] = 'a'; pMSADPCM->pucEncodedData[72] = 'c'; pMSADPCM->pucEncodedData[73] = 't'; pMSADPCM->pucEncodedData[74] = 4; pMSADPCM->pucEncodedData[75] = 0; pMSADPCM->pucEncodedData[76] = 0; pMSADPCM->pucEncodedData[77] = 0; pMSADPCM->pucEncodedData[78] = 0; pMSADPCM->pucEncodedData[79] = 0; pMSADPCM->pucEncodedData[80] = 0; pMSADPCM->pucEncodedData[81] = 0; // // Add the "data" chunk in the encoded data buffer. // pMSADPCM->pucEncodedData[82] = 'd'; pMSADPCM->pucEncodedData[83] = 'a'; pMSADPCM->pucEncodedData[84] = 't'; pMSADPCM->pucEncodedData[85] = 'a'; pMSADPCM->pucEncodedData[86] = 0; pMSADPCM->pucEncodedData[87] = 0; pMSADPCM->pucEncodedData[88] = 0; pMSADPCM->pucEncodedData[89] = 0; // // There are 90 bytes of valid data in the encoded data buffer. // pMSADPCM->usValid = 90; // // The initial length of the encoded data is 0. // pMSADPCM->ulLength = 0; pMSADPCM->ulTimePos = 0; pMSADPCM->ulDataValid = 0; // // There is no input buffer. // pMSADPCM->pBuffer = 0; // // Success. // return(1);}//****************************************************************************//// The codec plug-in entry point for the MS ADPCM encoder/decoder.////****************************************************************************unsigned longMSADPCMIoctl(unsigned long ulIoctl, unsigned long ulParam1, unsigned long ulParam2, unsigned long ulParam3, unsigned long ulParam4){ // // Determine what to do based on the specified IOCTL. // switch(ulIoctl) { // // Return the name for this codec. // case IOCTL_CODEC_GETNAME: { const unsigned short **ppusName; // // The secod parameter is a pointer for the name. // ppusName = (const unsigned short **)ulParam2; // // Return the name of this codec. The first four characters are // the short name and the string starting at the fifth character // is the long name. // *ppusName = pusCodecName; // // Success. // return(1); } // // Return the name of the artist. // case IOCTL_CODEC_GETARTIST: { unsigned short **ppusName; // // The second parameter is a pointer for the name. // ppusName = (unsigned short **)ulParam2; // // There is no way to store the artist name in a MS ADPCM file. // *ppusName = 0; // // Success. // return(1); } //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -