Author Topic: Save Wav file with same format  (Read 342 times)

moz

  • Posts: 10
Save Wav file with same format
« on: 12 Apr '19 - 12:18 »
Hi there,

my use case is to open a wav file, alter the data by applying some dsp algorithms and save it out again with the same format.

So for example I have a 24bit 48kHz file that I want to get audio info as float data, apply some dsp and save it out as 24bit 48kHz again.

Here is what I did so far. It does however create a file with noise:

Code: [Select]
HSTREAM stream = BASS_StreamCreateFile(false, filename, 0, 0, BASS_STREAM_DECODE | /BASS_SAMPLE_FLOAT);

BASS_CHANNELINFO info;
BASS_ChannelGetInfo(stream, &info);

FILE *fp;
WAVEFORMATEX wf;
DWORD p;
QWORD pos;

pos = BASS_ChannelGetLength(stream, BASS_POS_BYTE);

fp = fopen("C:\\Test\\Test\\test.wav", "wb");

if(fp == NULL)
{
return false;
}

wf.wFormatTag = 1;
wf.nChannels = info.chans;
wf.wBitsPerSample = info.origres;
wf.nBlockAlign = wf.nChannels*wf.wBitsPerSample / 8;
wf.nSamplesPerSec = info.freq;
wf.nAvgBytesPerSec = wf.nSamplesPerSec*wf.nBlockAlign;

fwrite("RIFF\0\0\0\0WAVEfmt \20\0\0\0", 20, 1, fp);
fwrite(&wf, 16, 1, fp);
fwrite("data\0\0\0\0", 8, 1, fp);

// deal with sample data
float buffer[10000];

while (!_kbhit() && BASS_ChannelIsActive(stream)) {
int c = BASS_ChannelGetData(stream, buffer, 20000);

fwrite(buffer, sizeof(float), c, fp);
pos = BASS_ChannelGetPosition(stream, BASS_POS_BYTE);

fflush(stdout);
}

fflush(stdout);
// complete WAV header
fflush(fp);
p = ftell(fp);
fseek(fp, 4, SEEK_SET);
_putw(le_32(p - 8), fp);
fflush(fp);
fseek(fp, 40, SEEK_SET);
_putw(le_32(p - 44), fp);
fflush(fp);
fclose(fp);

BASS_SampleFree(sample);
BASS_Free();


So basically what I would like to do is open a wav file, read its data as floats, manipulate them and generate an altered file again with the same format as the input file.
So a 16bit/44.1kHz should result in an altered 16bit/44.1kHz, a 24bit/48kHz should result in a 24bit/48kHz and so on.

Any help would be appreciated.

thanks,
Moz
« Last Edit: 12 Apr '19 - 14:53 by moz »

Ian @ un4seen

  • Administrator
  • Posts: 21979
Re: Save Wav file with same format
« Reply #1 on: 12 Apr '19 - 15:00 »
The easiest way to do it would be with the BASSenc add-on, which includes a WAV writing option. You would call BASS_Encode_Start on the stream with the BASS_ENCODE_PCM and BASS_ENCODE_FP_XXX flags. The stream's data will then be written to a WAV file within the BASS_ChannelGetData call, after any DSP/FX have been applied (depending on the "priority" values). Your code above could be modified something like this:

Code: [Select]
HSTREAM stream = BASS_StreamCreateFile(false, filename, 0, 0, BASS_STREAM_DECODE | BASS_SAMPLE_FLOAT);

BASS_CHANNELINFO info;
BASS_ChannelGetInfo(stream, &info);
DWORD fpflag = 0;
if (info.origres == 32)
fpflag = BASS_ENCODE_FP_32BIT;
if (info.origres == 24)
fpflag = BASS_ENCODE_FP_24BIT;
if (info.origres == 16)
fpflag = BASS_ENCODE_FP_16BIT;
if (info.origres == 8)
fpflag = BASS_ENCODE_FP_8BIT;
BASS_Encode_Start(stream, "C:\\Test\\test.wav", BASS_ENCODE_PCM | fpflag, NULL, NULL); // set a WAV writer on the stream

BASS_ChannelSetDSP(stream, DspProc, NULL, 0); // set your DSP function on the stream

float buffer[10000];
while (!_kbhit() && BASS_ChannelIsActive(stream)) {
int c = BASS_ChannelGetData(stream, buffer, sizeof(buffer));
}

BASS_Encode_Stop(stream); // close the WAV writer
BASS_StreamFree(stream);
BASS_Free();

Please see the BASS_Encode_Start documentation for details.

moz

  • Posts: 10
Re: Save Wav file with same format
« Reply #2 on: 12 Apr '19 - 19:33 »
oh wow. that looks pretty slick. Gonna have to check this out.

thanks so much for the sample code.