i use libmad to help work. but it doesn't support 8bit 8khz mono wav format. most of coders know it well, i think. the main code shows as below: /* WAV structure * Used in CbMpegAudioDecoder when instructed to write a * WAV header to the output file. */ struct WAV_HEADER { int RIFF; // 'R','I','F','F' int size; // size of wave file from here on int WAVE; // 'W','A','V','E' int fmt; //'f','m','t',' ' int wFormatLength; // The length of the TAG format short wFormatTag; // should be 1 for PCM type data short nChannels; // Mono = 1, Stereo = 2, etc. int nSampleRate; // 8000, 44100, etc. int nAvgBytesPerSec; // Average Data Rate short nBlockAlign; // 1 for 8 bit data, 2 for 16 bit short wBitsPerSample; // 8 for 8 bit data, 16 for 16 bit int data; // 'd','a','t','a' int datasize; // size of data from here on }; WAV_HEADER wav_header; /* my WAV header */ ... ... wav_header.nChannels = 1; wav_header.nSampleRate = 8000; /* Once decoded the frame is synthesized to PCM samples. No errors * are reported by mad_synth_frame(); */ mad_synth_frame(&Synth, &Frame); /* Synthesized samples must be converted from libmad's fixed * point number to the consumer format. Here we use unsigned * 16 bit big endian integers on two channels. Integer samples * are temporarily stored in a buffer that is flushed when * full. */ for(i=0; i < Synth.pcm.length; i++) { signed short Sample; /* Left channel */ Sample=Scale(Synth.pcm.samples[0][i], &gRand); /* output in 16 bit little-endian */ /* *(OutputPtr++)=Sample>>8; //Originally big-endian *(OutputPtr++)=Sample&0xff; */ *(OutputPtr++)=((Sample>>0) & 0xff); *(OutputPtr++)=((Sample>>8) & 0xff); //char leftsample = Sample && 0xff; /* Right channel. If the decoded stream is monophonic then * the right output channel is the same as the left one. */ if(MAD_NCHANNELS(&Frame.header)==2) Sample=Scale(Synth.pcm.samples[1][i], &gRand); /* output in 16 bit little-endian */ /* *(OutputPtr++)=Sample>>8; //Originally big-endian *(OutputPtr++)=Sample&0xff; */ *(OutputPtr++)=((Sample>>0) & 0xff); *(OutputPtr++)=((Sample>>8) & 0xff); /* Flush the output buffer if it is full. */ if(OutputPtr == OutputBufferEnd) { if(fwrite(OutputBuffer, 1, OUTPUT_BUFFER_SIZE, OutputFp)!=OUTPUT_BUFFER_SIZE) { sprintf(StatMsg, "PCM write error (%s).\n", strerror(errno)); Status=2; break; } OutputPtr=OutputBuffer; } } }while(1);and the Scale() is as following: /*************************************************************************** * * A little more advanced scaling routine based on madplay's * audio_linear_dither() function. Rather than simply rounding the 24 bit * number down to 16 bits (as MadFixedToSshort() in madlld does), it performs * dithering, which is the addition of a random number to the least * significant bits (LSB) of the sample that targets the LSB at the 16 bit * . CbMpegAudioDecoder() uses this to perform its scaling before output.**************************************************************************** / static inline signed short Scale(mad_fixed_t sample, mad_fixed_t *gRandom) { unsigned int scalebits; mad_fixed_t output, mask, rnd; /* bias */ output = sample + (1L << (MAD_F_FRACBITS + 1 - 16 - 1)); //output = sample + (1L << (MAD_F_FRACBITS + 1 - 8 - 1)); scalebits = MAD_F_FRACBITS + 1 - 16; //scalebits = MAD_F_FRACBITS + 1 - 8; mask = (1L << scalebits) - 1; /* dither */ rnd = Prng(*gRandom); output += (rnd & mask) - (*gRandom & mask); *gRandom = rnd; /* clip */ if (output >= MAD_F_ONE) output = MAD_F_ONE - 1; else if (output < -MAD_F_ONE) output = -MAD_F_ONE; /* quantize */ output &= ~mask; /* scale */ return output >> scalebits; }i'm new to audio programming, i don't know how to resample, worse, i haven't found any stuff about audio conversation in converting other format into 8bit 8000hz mono wav format. i think, it would fit my need if modifying the above code properly. i tried for many times, unfortunately, it sounds strange:-( how to modify the code to fit my need? thank you very much.
most of coders know it well, i think.
the main code shows as below:
/* WAV structure
* Used in CbMpegAudioDecoder when instructed to write a
* WAV header to the output file.
*/
struct WAV_HEADER {
int RIFF; // 'R','I','F','F'
int size; // size of wave file from here on
int WAVE; // 'W','A','V','E'
int fmt; //'f','m','t',' '
int wFormatLength; // The length of the TAG format
short wFormatTag; // should be 1 for PCM type data
short nChannels; // Mono = 1, Stereo = 2, etc.
int nSampleRate; // 8000, 44100, etc.
int nAvgBytesPerSec; // Average Data Rate
short nBlockAlign; // 1 for 8 bit data, 2 for 16 bit
short wBitsPerSample; // 8 for 8 bit data, 16 for 16 bit
int data; // 'd','a','t','a'
int datasize; // size of data from here on
};
WAV_HEADER wav_header; /* my WAV header */
... ...
wav_header.nChannels = 1;
wav_header.nSampleRate = 8000; /* Once decoded the frame is synthesized to PCM samples. No errors
* are reported by mad_synth_frame();
*/
mad_synth_frame(&Synth, &Frame); /* Synthesized samples must be converted from libmad's fixed
* point number to the consumer format. Here we use unsigned
* 16 bit big endian integers on two channels. Integer samples
* are temporarily stored in a buffer that is flushed when
* full.
*/
for(i=0; i < Synth.pcm.length; i++)
{
signed short Sample; /* Left channel */
Sample=Scale(Synth.pcm.samples[0][i], &gRand); /* output in 16 bit little-endian */
/*
*(OutputPtr++)=Sample>>8; //Originally big-endian
*(OutputPtr++)=Sample&0xff;
*/
*(OutputPtr++)=((Sample>>0) & 0xff);
*(OutputPtr++)=((Sample>>8) & 0xff); //char leftsample = Sample && 0xff; /* Right channel. If the decoded stream is monophonic then
* the right output channel is the same as the left one.
*/
if(MAD_NCHANNELS(&Frame.header)==2)
Sample=Scale(Synth.pcm.samples[1][i], &gRand); /* output in 16 bit little-endian */
/*
*(OutputPtr++)=Sample>>8; //Originally big-endian
*(OutputPtr++)=Sample&0xff;
*/
*(OutputPtr++)=((Sample>>0) & 0xff);
*(OutputPtr++)=((Sample>>8) & 0xff); /* Flush the output buffer if it is full. */
if(OutputPtr == OutputBufferEnd)
{
if(fwrite(OutputBuffer, 1, OUTPUT_BUFFER_SIZE,
OutputFp)!=OUTPUT_BUFFER_SIZE)
{
sprintf(StatMsg, "PCM write error (%s).\n",
strerror(errno));
Status=2;
break;
}
OutputPtr=OutputBuffer;
}
} }while(1);and the Scale() is as following:
/***************************************************************************
*
* A little more advanced scaling routine based on madplay's
* audio_linear_dither() function. Rather than simply rounding the 24 bit
* number down to 16 bits (as MadFixedToSshort() in madlld does), it
performs
* dithering, which is the addition of a random number to the least
* significant bits (LSB) of the sample that targets the LSB at the 16 bit
* . CbMpegAudioDecoder() uses this to perform its scaling before
output.****************************************************************************
/
static inline signed short Scale(mad_fixed_t sample, mad_fixed_t *gRandom)
{
unsigned int scalebits;
mad_fixed_t output, mask, rnd; /* bias */
output = sample + (1L << (MAD_F_FRACBITS + 1 - 16 - 1));
//output = sample + (1L << (MAD_F_FRACBITS + 1 - 8 - 1)); scalebits = MAD_F_FRACBITS + 1 - 16;
//scalebits = MAD_F_FRACBITS + 1 - 8;
mask = (1L << scalebits) - 1; /* dither */
rnd = Prng(*gRandom);
output += (rnd & mask) - (*gRandom & mask);
*gRandom = rnd; /* clip */
if (output >= MAD_F_ONE)
output = MAD_F_ONE - 1;
else if (output < -MAD_F_ONE)
output = -MAD_F_ONE; /* quantize */
output &= ~mask; /* scale */
return output >> scalebits;
}i'm new to audio programming, i don't know how to resample, worse, i haven't
found any stuff about
audio conversation in converting other format into 8bit 8000hz mono wav
format.
i think, it would fit my need if modifying the above code properly.
i tried for many times, unfortunately, it sounds strange:-(
how to modify the code to fit my need?
thank you very much.
就是把44.1khz, 16bit, stereo格式的PCM 数据,转换为 8000 hz, 8bit, mono 格式的wave文件.
就这个要求.