editor/bass-sys/linux/bass24/writewav/writewav.c
2021-01-07 21:37:50 -06:00

168 lines
4.4 KiB
C

/*
BASS console WAV writer
Copyright (c) 2002-2008 Un4seen Developments Ltd.
*/
#include <stdlib.h>
#include <stdio.h>
#include "bass.h"
#ifdef _WIN32 // Windows
#include <conio.h>
#else // OSX
#include <sys/types.h>
#include <sys/time.h>
#include <termios.h>
#include <string.h>
int _kbhit()
{
int r;
fd_set rfds;
struct timeval tv;
struct termios term, oterm;
tcgetattr(0, &oterm);
memcpy(&term, &oterm, sizeof(term));
cfmakeraw(&term);
tcsetattr(0, TCSANOW, &term);
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = tv.tv_usec = 0;
r = select(1, &rfds, NULL, NULL, &tv);
tcsetattr(0, TCSANOW, &oterm);
return r;
}
#endif
#ifdef _BIG_ENDIAN
inline DWORD le_32(DWORD v)
{
return (v >> 24) | ((v >> 8) & 0xff00) | ((v & 0xff00) << 8) | (v << 24);
}
inline WORD le_16(WORD v)
{
return (v >> 8) | (v << 8);
}
#else
#define le_32(v) (v)
#define le_16(v) (v)
#endif
// display error messages
void Error(const char *text)
{
printf("Error(%d): %s\n", BASS_ErrorGetCode(), text);
BASS_Free();
exit(0);
}
void main(int argc, char **argv)
{
BASS_CHANNELINFO info;
DWORD chan, p;
QWORD pos;
FILE *fp;
short buf[10000];
WAVEFORMATEX wf;
printf("BASS WAV writer example : MOD/MPx/OGG -> BASS.WAV\n"
"-------------------------------------------------\n");
// check the correct BASS was loaded
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
printf("An incorrect version of BASS was loaded");
return;
}
if (argc != 2) {
printf("\tusage: writewav <file>\n");
return;
}
// initalize "no sound" device
if (!BASS_Init(0, 44100, 0, 0, NULL))
Error("Can't initialize device");
// try streaming the file/url
if ((chan = BASS_StreamCreateFile(FALSE, argv[1], 0, 0, BASS_STREAM_DECODE))
|| (chan = BASS_StreamCreateURL(argv[1], 0, BASS_STREAM_DECODE | BASS_STREAM_BLOCK, 0, 0))) {
pos = BASS_ChannelGetLength(chan, BASS_POS_BYTE);
if (pos == -1) // length not available
printf("streaming file");
else
#ifdef _WIN32
printf("streaming file [%I64u bytes]", pos);
#else
printf("streaming file [%llu bytes]", pos);
#endif
} else {
// try loading the MOD (with sensitive ramping, and calculate the duration)
if (!(chan = BASS_MusicLoad(FALSE, argv[1], 0, 0, BASS_MUSIC_DECODE | BASS_MUSIC_RAMP | BASS_MUSIC_PRESCAN, 0)))
// not a MOD either
Error("Can't play the file");
{ // count channels
float dummy;
for (p = 0; BASS_ChannelGetAttribute(chan, BASS_ATTRIB_MUSIC_VOL_CHAN + p, &dummy); p++);
}
printf("MOD music \"%s\" [%u chans, %u orders]",
BASS_ChannelGetTags(chan, BASS_TAG_MUSIC_NAME), p, (DWORD)BASS_ChannelGetLength(chan, BASS_POS_MUSIC_ORDER));
pos = BASS_ChannelGetLength(chan, BASS_POS_BYTE);
}
// display the time length
if (pos && pos != -1) {
p = (DWORD)BASS_ChannelBytes2Seconds(chan, pos);
printf(" %u:%02u\n", p / 60, p % 60);
} else // no time length available
printf("\n");
if (!(fp = fopen("bass.wav", "wb"))) Error("Can't create file");
printf("writing to BASS.WAV file... press a key to stop\n");
// write WAV header
BASS_ChannelGetInfo(chan, &info);
wf.wFormatTag = 1;
wf.nChannels = info.chans;
wf.wBitsPerSample = (info.flags & BASS_SAMPLE_8BITS ? 8 : 16);
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
wf.nSamplesPerSec = info.freq;
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
#ifdef _BIG_ENDIAN // swap byte order
wf.wFormatTag = le_16(wf.wFormatTag);
wf.nChannels = le_16(wf.nChannels);
wf.wBitsPerSample = le_16(wf.wBitsPerSample);
wf.nBlockAlign = le_16(wf.nBlockAlign);
wf.nSamplesPerSec = le_32(wf.nSamplesPerSec);
wf.nAvgBytesPerSec = le_32(wf.nAvgBytesPerSec);
#endif
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);
while (!_kbhit() && BASS_ChannelIsActive(chan)) {
int c = BASS_ChannelGetData(chan, buf, 20000);
#ifdef _BIG_ENDIAN
if (!(info.flags & BASS_SAMPLE_8BITS)) // swap 16-bit byte order
for (p = 0; p < c / 2; p++) buf[p] = le_16(buf[p]);
#endif
fwrite(buf, 1, c, fp);
pos = BASS_ChannelGetPosition(chan, BASS_POS_BYTE);
#ifdef _WIN32
printf("pos %09I64u\r", pos);
#else
printf("pos %09llu\r", pos);
#endif
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_Free();
}