diff options
Diffstat (limited to 'utils/midiplay/wave_writer.c')
-rwxr-xr-x | utils/midiplay/wave_writer.c | 214 |
1 files changed, 132 insertions, 82 deletions
diff --git a/utils/midiplay/wave_writer.c b/utils/midiplay/wave_writer.c index e8ee10c..bdee5d7 100755 --- a/utils/midiplay/wave_writer.c +++ b/utils/midiplay/wave_writer.c @@ -26,145 +26,195 @@ enum { header_size = 0x2C }; typedef short sample_t; -static unsigned char* buf; -static FILE* file; -static long sample_count_; -static long sample_rate_; -static long buf_pos; -static int chan_count; - -static void exit_with_error( const char* str ) +struct Context { - fprintf(stderr, "WAVE Writer Error: %s\n", str ); + unsigned char *m_buf; + FILE *m_file; + long m_sample_count; + long m_sample_rate; + long m_buf_pos; + int m_chan_count; +}; + +static struct Context *g_wwContext = NULL; + +static void exit_with_error(const char *str) +{ + fprintf(stderr, "WAVE Writer Error: %s\n", str); fflush(stderr); } -int wave_open( long sample_rate, const char* filename ) +int wave_open(long sample_rate, const char *filename) +{ + g_wwContext = ctx_wave_open(sample_rate, filename); + return g_wwContext ? 0 : -1; +} + +void wave_enable_stereo(void) +{ + ctx_wave_enable_stereo(g_wwContext); +} + +void wave_write(short const *in, long remain) +{ + ctx_wave_write(g_wwContext, in, remain); +} + +long wave_sample_count(void) +{ + return ctx_wave_sample_count(g_wwContext); +} + +void wave_close(void) { - sample_count_ = 0; - sample_rate_ = sample_rate; - buf_pos = header_size; - chan_count = 1; + ctx_wave_close(g_wwContext); +} + + + +static void set_le32(void *p, unsigned long n) +{ + ((unsigned char *) p) [0] = (unsigned char) n & (0xFF); + ((unsigned char *) p) [1] = (unsigned char)(n >> 8) & (0xFF); + ((unsigned char *) p) [2] = (unsigned char)(n >> 16) & (0xFF); + ((unsigned char *) p) [3] = (unsigned char)(n >> 24) & (0xFF); +} - buf = (unsigned char*) malloc( buf_size * sizeof *buf ); - if ( !buf ) +void *ctx_wave_open(long sample_rate, const char *filename) +{ + struct Context *ctx = (struct Context*)malloc(sizeof(struct Context)); + if(!ctx) { - exit_with_error( "Out of memory" ); - return -1; + exit_with_error("Out of memory"); + return NULL; + } + + ctx->m_sample_count = 0; + ctx->m_sample_rate = sample_rate; + ctx->m_buf_pos = header_size; + ctx->m_chan_count = 1; + + ctx->m_buf = (unsigned char *) malloc(buf_size); + if(!ctx->m_buf) + { + exit_with_error("Out of memory"); + free(ctx); + return NULL; } #if !defined(_WIN32) || defined(__WATCOMC__) - file = fopen( filename, "wb" ); + ctx->m_file = fopen(filename, "wb"); #else wchar_t widePath[MAX_PATH]; int size = MultiByteToWideChar(CP_UTF8, 0, filename, strlen(filename), widePath, MAX_PATH); widePath[size] = '\0'; - file = _wfopen( widePath, L"wb" ); + ctx->m_file = _wfopen(widePath, L"wb"); #endif - if (!file) + if(!ctx->m_file) { - exit_with_error( "Couldn't open WAVE file for writing" ); - return -1; + exit_with_error("Couldn't open WAVE file for writing"); + free(ctx); + return NULL; } - setvbuf( file, 0, _IOFBF, 32 * 1024L ); - return 0; + setvbuf(ctx->m_file, 0, _IOFBF, 32 * 1024L); + return ctx; } -void wave_enable_stereo( void ) +void ctx_wave_enable_stereo(void *ctx) { - chan_count = 2; + struct Context *wWriter = (struct Context *)ctx; + wWriter->m_chan_count = 2; } -static void flush_() + +static void flush_(struct Context *ctx) { - if ( buf_pos && !fwrite( buf, (size_t)buf_pos, 1, file ) ) - exit_with_error( "Couldn't write WAVE data" ); - buf_pos = 0; + if(ctx->m_buf_pos && !fwrite(ctx->m_buf, (size_t)ctx->m_buf_pos, 1, ctx->m_file)) + exit_with_error("Couldn't write WAVE data"); + ctx->m_buf_pos = 0; } -void wave_write( short const* in, long remain ) +void ctx_wave_write(void *ctx, const short *in, long remain) { - sample_count_ += remain; - while ( remain ) + struct Context *wWriter = (struct Context *)ctx; + wWriter->m_sample_count += remain; + while(remain) { - if ( buf_pos >= buf_size ) - flush_(); - + if(wWriter->m_buf_pos >= buf_size) + flush_(wWriter); { - unsigned char* p = &buf [buf_pos]; - long n = (buf_size - (unsigned long)buf_pos) / sizeof (sample_t); - if ( n > remain ) + unsigned char *p = &wWriter->m_buf [wWriter->m_buf_pos]; + long n = (buf_size - (unsigned long)wWriter->m_buf_pos) / sizeof(sample_t); + if(n > remain) n = remain; remain -= n; /* convert to LSB first format */ - while ( n-- ) + while(n--) { int s = *in++; *p++ = (unsigned char) s & (0x00FF); - *p++ = (unsigned char) (s >> 8) & (0x00FF); + *p++ = (unsigned char)(s >> 8) & (0x00FF); } - buf_pos = p - buf; - assert( buf_pos <= buf_size ); + wWriter->m_buf_pos = p - wWriter->m_buf; + assert(wWriter->m_buf_pos <= buf_size); } } } -long wave_sample_count( void ) +long ctx_wave_sample_count(void *ctx) { - return sample_count_; + struct Context *wWriter = (struct Context *)ctx; + return wWriter->m_sample_count; } -static void set_le32( void* p, unsigned long n ) +void ctx_wave_close(void *ctx) { - ((unsigned char*) p) [0] = (unsigned char) n & (0xFF); - ((unsigned char*) p) [1] = (unsigned char) (n >> 8) & (0xFF); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16) & (0xFF); - ((unsigned char*) p) [3] = (unsigned char) (n >> 24) & (0xFF); -} + struct Context *wWriter = (struct Context *)ctx; + if(!wWriter) + return; -void wave_close( void ) -{ - if ( file ) + if(wWriter->m_file) { /* generate header */ unsigned char h [header_size] = { - 'R','I','F','F', - 0,0,0,0, /* length of rest of file */ - 'W','A','V','E', - 'f','m','t',' ', - 0x10,0,0,0, /* size of fmt chunk */ - 1,0, /* uncompressed format */ - 0,0, /* channel count */ - 0,0,0,0, /* sample rate */ - 0,0,0,0, /* bytes per second */ - 0,0, /* bytes per sample frame */ - 16,0, /* bits per sample */ - 'd','a','t','a', - 0,0,0,0, /* size of sample data */ + 'R', 'I', 'F', 'F', + 0, 0, 0, 0, /* length of rest of file */ + 'W', 'A', 'V', 'E', + 'f', 'm', 't', ' ', + 0x10, 0, 0, 0, /* size of fmt chunk */ + 1, 0, /* uncompressed format */ + 0, 0, /* channel count */ + 0, 0, 0, 0, /* sample rate */ + 0, 0, 0, 0, /* bytes per second */ + 0, 0, /* bytes per sample frame */ + 16, 0, /* bits per sample */ + 'd', 'a', 't', 'a', + 0, 0, 0, 0, /* size of sample data */ /* ... */ /* sample data */ }; - long ds = sample_count_ * (long)sizeof (sample_t); - int frame_size = chan_count * (long)sizeof (sample_t); + long ds = wWriter->m_sample_count * (long)sizeof(sample_t); + int frame_size = wWriter->m_chan_count * (long)sizeof(sample_t); - set_le32( h + 0x04, header_size - 8 + ds ); - h [0x16] = (unsigned char)chan_count; - set_le32( h + 0x18, (unsigned long)sample_rate_ ); - set_le32( h + 0x1C, (unsigned long)sample_rate_ * (unsigned long)frame_size ); + set_le32(h + 0x04, header_size - 8 + ds); + h [0x16] = (unsigned char)wWriter->m_chan_count; + set_le32(h + 0x18, (unsigned long)wWriter->m_sample_rate); + set_le32(h + 0x1C, (unsigned long)wWriter->m_sample_rate * (unsigned long)frame_size); h [0x20] = (unsigned char)frame_size; - set_le32( h + 0x28, (unsigned long)ds ); + set_le32(h + 0x28, (unsigned long)ds); - flush_(); + flush_(wWriter); /* write header */ - fseek( file, 0, SEEK_SET ); - fwrite( h, header_size, 1, file ); - fclose( file ); - file = 0; - free( buf ); - buf = 0; + fseek(wWriter->m_file, 0, SEEK_SET); + fwrite(h, header_size, 1, wWriter->m_file); + fclose(wWriter->m_file); + wWriter->m_file = 0; + free(wWriter->m_buf); + wWriter->m_buf = 0; } + free(wWriter); } |