91 lines
2.4 KiB
C
91 lines
2.4 KiB
C
|
|
||
|
void wav_write_uint32(byte *data, uint value) {
|
||
|
for(int h = 0; h < 4; h++) {
|
||
|
data[h] = ((uint)((value >> (8*h) & 0xff)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wav_write_uint16(byte *data, ushort value) {
|
||
|
for(int h = 0; h < 2; h++) {
|
||
|
data[h] = ((ushort)((value >> (8*h) & 0xff)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wav_write_header(byte *data, uint samplerate, ushort channels, uint samples, ushort bytes) {
|
||
|
memcpy(data+0, wav_hdr, 4);
|
||
|
wav_write_uint32(data+4, 36 + samples * ((uint)channels) * ((uint)bytes));
|
||
|
memcpy(data+8, wav_format, 4);
|
||
|
memcpy(data+12, wav_hdr_fmt, 4);
|
||
|
wav_write_uint32(data+16, 16);
|
||
|
wav_write_uint16(data+20, 1);
|
||
|
wav_write_uint16(data+22, channels);
|
||
|
wav_write_uint32(data+24, samplerate);
|
||
|
wav_write_uint32(data+28, samplerate * ((uint)channels) * ((uint)bytes));
|
||
|
wav_write_uint16(data+32, channels * bytes);
|
||
|
wav_write_uint16(data+34, 8 * bytes);
|
||
|
memcpy(data+36, wav_hdr_data, 4);
|
||
|
wav_write_uint32(data+40, samples * ((uint)channels) * ((uint)bytes));
|
||
|
}
|
||
|
|
||
|
byte wav_open(wav_handle *wav, const char *filename, uint samplerate, ushort channels, ushort bytes) {
|
||
|
int err;
|
||
|
FILE *fd = fopen(filename, "wb");
|
||
|
if(fd == NULL) {
|
||
|
err = errno;
|
||
|
snd_loge(STR_WAV_OPNERR, filename, strerror(err), err);
|
||
|
return 0;
|
||
|
}
|
||
|
byte pad[WAV_HDRSIZE];
|
||
|
memset(pad, 0, WAV_HDRSIZE);
|
||
|
if(fwrite(pad, 1, WAV_HDRSIZE, fd) != WAV_HDRSIZE) {
|
||
|
snd_loge(STR_WAV_EIO, filename);
|
||
|
fclose(fd);
|
||
|
return 0;
|
||
|
}
|
||
|
wav->fd = fd;
|
||
|
wav->samplerate = samplerate;
|
||
|
wav->channels = channels;
|
||
|
wav->bytes = bytes;
|
||
|
wav->samples = 0;
|
||
|
wav->filename = filename;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
byte wav_close(wav_handle *wav) {
|
||
|
if(wav->fd == NULL) {
|
||
|
return 0;
|
||
|
}
|
||
|
int err;
|
||
|
if(fseek(wav->fd, 0L, SEEK_SET)) {
|
||
|
err = errno;
|
||
|
snd_loge(STR_WAV_EGEN, wav->filename, strerror(err), err);
|
||
|
fclose(wav->fd);
|
||
|
return 0;
|
||
|
}
|
||
|
byte header[WAV_HDRSIZE];
|
||
|
wav_write_header(header, wav->samplerate, wav->channels, wav->samples, wav->bytes);
|
||
|
if(fwrite(header, 1, WAV_HDRSIZE, wav->fd) != WAV_HDRSIZE) {
|
||
|
snd_loge(STR_WAV_EIO, wav->filename);
|
||
|
fclose(wav->fd);
|
||
|
return 0;
|
||
|
}
|
||
|
fclose(wav->fd);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void wav_write16(wav_handle *wav, short *samples, uint count) {
|
||
|
if(wav->fd == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
for(int c = 0; c < (count * ((uint)wav->channels)); c++) {
|
||
|
wav_write_uint16((wav->buffer)+(c*2), samples[c]);
|
||
|
}
|
||
|
if(fwrite(wav->buffer, 1, 2 * ((uint)wav->channels) * count, wav->fd) != (2 * ((uint)wav->channels) * count)) {
|
||
|
snd_loge(STR_WAV_EIO, wav->filename);
|
||
|
fclose(wav->fd);
|
||
|
wav->fd = NULL;
|
||
|
return;
|
||
|
}
|
||
|
wav->samples += count;
|
||
|
}
|