Here's some code that does re-sampling of audio. No idea if it'll be of any use to you - googling for how to do it it was not much easier than implementing it. It was used for up-sampling 8363 samples/sec sound into 44100 samples/sec sound. It was used for working with the audio samples as found in .XM files (somewhat similar to Amiga .mod files, or less-so, .MIDI files)
There's bound to be a bunch of code here that's useless to you, but I've no idea which format your .WAV files are, so I'll leave it to you to use that which you need. You're also on-your-own when it comes to reading the samples from a WAV file - in my instance, the header of the samples is different to the .WAV file header - my data also came with a single header - the wav file contains a number of chunks, each of these has its own header.
The re-sampling is of the linear variety.
You can determine the play-time of the WAV file by looking at a number of the chunk headers inside it. Don't ask me how, as I haven't bothered to do it, and don't know. (nor am I interested)
This page seems to be an easier read than the Wikipedia WAV page - http://www.sonicspot.com/guide/wavefiles.html[^]
float *convert8tofloat(char *input, int numSamples)
{
float *result = new float[numSamples];
int i;
for (i=0; i<numSamples; i++)
{
result[i] = input[i] / 128.0; }
return result;
}
float *convert16tofloat(short *input, int numSamples)
{
float *result = new float[numSamples];
int i;
for (i=0; i<numSamples; i++)
{
result[i] = (int)input[i] / 32768.0; }
return result;
}
char interpolate8(char val1, char val2, float t)
{
short difference;
difference = val2 - val1;
return val1 + t*difference;
}
short interpolate16(short val1, short val2, float t)
{
int difference;
difference = val2 - val1;
return val1 + t*difference;
}
float interpolateFloat32(float val1, float val2, float t)
{
float difference;
difference = val2 - val1;
return val1 + t*difference;
}
char *resample8Interp(char *input, int numSamplesIn, int numSamplesOut)
{
char *output;
output = new char[numSamplesOut];
float curIndex, proportion, step;
char curVal;
int i, intPart;
output[0] = input[0];
output[numSamplesOut-1] = input[numSamplesIn-1];
step = (float) (numSamplesIn-1) / (numSamplesOut-1);
for (i=1; i<numSamplesOut-1; i++)
{
curIndex = (float) i * step;
intPart = floor(curIndex);
proportion = curIndex - intPart;
curVal = interpolate8(input[intPart], input[intPart+1], proportion);
output[i] = curVal;
}
return(output);
}
short *resample16Interp(short *input, int numSamplesIn, int numSamplesOut)
{
short *output;
output = new short[numSamplesOut];
float curIndex, proportion, step;
short curVal;
int i, intPart;
output[0] = input[0];
output[numSamplesOut-1] = input[numSamplesIn-1];
step = (float) (numSamplesIn-1) / (numSamplesOut-1);
for (i=1; i<numSamplesOut-1; i++)
{
curIndex = (float) i * step;
intPart = floor(curIndex);
proportion = curIndex - intPart;
curVal = interpolate16(input[intPart], input[intPart+1], proportion);
output[i] = curVal;
}
return(output);
}
float *reSampleFloat32(float *srcArray, int origNumSamples, int origRate, int newRate, int &outNumSamples)
{
outNumSamples = (origNumSamples * newRate) / origRate;
float *output = new float[outNumSamples];
int i, intPart;
float fractionalPart, curIndex, curVal, step;
step = (float)(origNumSamples-1) / (outNumSamples-1);
output[0] = srcArray[0];
output[outNumSamples-1] = srcArray[origNumSamples-1];
for (i=0; i<outNumSamples; i++)
{
curIndex = step * i;
intPart = floor(curIndex);
fractionalPart = curIndex - intPart;
curVal = interpolateFloat32(srcArray[intPart], srcArray[intPart+1], fractionalPart);
output[i] = curVal;
}
return output;
}
Here's some examples of implementation. I dont remember a thing about the code, haven't touched it in years - nor am I inclined to. That's an exercise for you. I assume some of the comments are misleading - I just changed the one that says "only works for 16 bit samples" - it had said "only works for 8 bit samples, which was clearly inaccurate.
Finally, not that in my case I wanted to convert the samples to be a 32-bit floating point format in the range [-1..1] which simplifies drawing them to screen.
Good luck!
void onSmpListChange(HWND smpListBox, XMFile *mSong)
{
int curIns, curSmp;
HWND dlg = GetParent(smpListBox);
HWND insList = GetDlgItem(dlg, IDC_INS_LIST);
curIns = SendMessage(insList, LB_GETCURSEL, 0, 0);
curSmp = SendMessage(smpListBox, LB_GETCURSEL, 0, 0);
XMSample *curSample = &mSong->instruments[curIns].samples[curSmp];
int bits=8, numSamples = curSample->header.sampleLength;
float *tmpBuffer;
if (curSample->header.compression == 0)
SetDlgItemText(dlg, IDC_COMP, "Delta");
else
{
SetDlgItemText(dlg, IDC_COMP, "ADPCM");
return;
}
if (curSample->header.type & 0x16)
{
printf("Resampling 16bit sound, %d samples - %20.20s\n", numSamples, curSample->header.sampleName);
numSamples /= 2;
SetDlgItemInt(dlg, IDC_BITS, 16, true);
char fileName[48];
strcpy(fileName, "16bit 8363hz.wav");
writeWavFile(fileName, curSample->data, numSamples, 16, 1, 8363);
short *sBuf = resample16Interp((short*)curSample->data, numSamples, 44100*numSamples / 8363);
strcpy(fileName, "16bit 44100hz.wav");
writeWavFile(fileName, sBuf, (44100*numSamples)/8363, 16, 1, 44100);
delete sBuf;
tmpBuffer = convert16tofloat((short*)curSample->data, numSamples);
}
else
{
printf("Resampling 8bit sound, %d samples - %20.20s\n", numSamples, curSample->header.sampleName);
SetDlgItemInt(dlg, IDC_BITS, 8, true);
char fileName[48];
strcpy(fileName, "8bit 8363hz.wav");
writeWavFile(fileName, curSample->data, numSamples, 8, 1, 8363);
char *cBuf = resample8Interp((char*)curSample->data, numSamples, 44100*numSamples / 8363);
strcpy(fileName, "8bit 44100hz.wav");
writeWavFile(fileName, cBuf, (44100*numSamples)/8363, 8, 1, 44100);
delete cBuf;
tmpBuffer = convert8tofloat((char*)curSample->data, numSamples);
}
SetDlgItemInt(dlg, IDC_NUM, numSamples, true);
SendDlgItemMessage(dlg, IDC_WAV_IMG, WM_SET_DATA, (WPARAM)tmpBuffer, (LPARAM)numSamples);
delete g_curSamples;
g_curSamples = tmpBuffer;
g_numSamples = numSamples;}
void onConvertBtn(HWND parentDlg)
{
float *mSamples;
int nSamples;
mSamples = reSampleFloat32(g_curSamples, g_numSamples, xmRate, 44100, nSamples);
SendDlgItemMessage(parentDlg, IDC_WAV_IMG2, WM_SET_DATA, (WPARAM)mSamples, (LPARAM)nSamples);
delete mSamples;
}
|