Mercurial > spc_convert
diff demo/wave_writer.c @ 0:e38dacceb958
initial import
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 21 Oct 2011 05:53:11 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/demo/wave_writer.c Fri Oct 21 05:53:11 2011 -0700 1.3 @@ -0,0 +1,153 @@ 1.4 +/* snes_spc 0.9.0. http://www.slack.net/~ant/ */ 1.5 + 1.6 +#include "wave_writer.h" 1.7 + 1.8 +#include <assert.h> 1.9 +#include <stdlib.h> 1.10 +#include <stdio.h> 1.11 + 1.12 +/* Copyright (C) 2003-2007 Shay Green. This module is free software; you 1.13 +can redistribute it and/or modify it under the terms of the GNU Lesser 1.14 +General Public License as published by the Free Software Foundation; either 1.15 +version 2.1 of the License, or (at your option) any later version. This 1.16 +module is distributed in the hope that it will be useful, but WITHOUT ANY 1.17 +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 1.18 +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 1.19 +details. You should have received a copy of the GNU Lesser General Public 1.20 +License along with this module; if not, write to the Free Software Foundation, 1.21 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 1.22 + 1.23 +enum { buf_size = 32768 * 2 }; 1.24 +enum { header_size = 0x2C }; 1.25 + 1.26 +typedef short sample_t; 1.27 + 1.28 +static unsigned char* buf; 1.29 +static FILE* file; 1.30 +static long sample_count_; 1.31 +static long sample_rate_; 1.32 +static long buf_pos; 1.33 +static int chan_count; 1.34 + 1.35 +static void exit_with_error( const char* str ) 1.36 +{ 1.37 + printf( "Error: %s\n", str ); getchar(); 1.38 + exit( EXIT_FAILURE ); 1.39 +} 1.40 + 1.41 +void wave_open( long sample_rate, const char* filename ) 1.42 +{ 1.43 + sample_count_ = 0; 1.44 + sample_rate_ = sample_rate; 1.45 + buf_pos = header_size; 1.46 + chan_count = 1; 1.47 + 1.48 + buf = (unsigned char*) malloc( buf_size * sizeof *buf ); 1.49 + if ( !buf ) 1.50 + exit_with_error( "Out of memory" ); 1.51 + 1.52 + file = fopen( filename, "wb" ); 1.53 + if ( !file ) 1.54 + exit_with_error( "Couldn't open WAVE file for writing" ); 1.55 + 1.56 + setvbuf( file, 0, _IOFBF, 32 * 1024L ); 1.57 +} 1.58 + 1.59 +void wave_enable_stereo( void ) 1.60 +{ 1.61 + chan_count = 2; 1.62 +} 1.63 + 1.64 +static void flush_() 1.65 +{ 1.66 + if ( buf_pos && !fwrite( buf, buf_pos, 1, file ) ) 1.67 + exit_with_error( "Couldn't write WAVE data" ); 1.68 + buf_pos = 0; 1.69 +} 1.70 + 1.71 +void wave_write( short const* in, long remain ) 1.72 +{ 1.73 + sample_count_ += remain; 1.74 + while ( remain ) 1.75 + { 1.76 + if ( buf_pos >= buf_size ) 1.77 + flush_(); 1.78 + 1.79 + { 1.80 + unsigned char* p = &buf [buf_pos]; 1.81 + long n = (buf_size - buf_pos) / sizeof (sample_t); 1.82 + if ( n > remain ) 1.83 + n = remain; 1.84 + remain -= n; 1.85 + 1.86 + /* convert to LSB first format */ 1.87 + while ( n-- ) 1.88 + { 1.89 + int s = *in++; 1.90 + *p++ = (unsigned char) s; 1.91 + *p++ = (unsigned char) (s >> 8); 1.92 + } 1.93 + 1.94 + buf_pos = p - buf; 1.95 + assert( buf_pos <= buf_size ); 1.96 + } 1.97 + } 1.98 +} 1.99 + 1.100 +long wave_sample_count( void ) 1.101 +{ 1.102 + return sample_count_; 1.103 +} 1.104 + 1.105 +static void set_le32( void* p, unsigned long n ) 1.106 +{ 1.107 + ((unsigned char*) p) [0] = (unsigned char) n; 1.108 + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); 1.109 + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); 1.110 + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); 1.111 +} 1.112 + 1.113 +void wave_close( void ) 1.114 +{ 1.115 + if ( file ) 1.116 + { 1.117 + /* generate header */ 1.118 + unsigned char h [header_size] = 1.119 + { 1.120 + 'R','I','F','F', 1.121 + 0,0,0,0, /* length of rest of file */ 1.122 + 'W','A','V','E', 1.123 + 'f','m','t',' ', 1.124 + 0x10,0,0,0, /* size of fmt chunk */ 1.125 + 1,0, /* uncompressed format */ 1.126 + 0,0, /* channel count */ 1.127 + 0,0,0,0, /* sample rate */ 1.128 + 0,0,0,0, /* bytes per second */ 1.129 + 0,0, /* bytes per sample frame */ 1.130 + 16,0, /* bits per sample */ 1.131 + 'd','a','t','a', 1.132 + 0,0,0,0, /* size of sample data */ 1.133 + /* ... */ /* sample data */ 1.134 + }; 1.135 + long ds = sample_count_ * sizeof (sample_t); 1.136 + int frame_size = chan_count * sizeof (sample_t); 1.137 + 1.138 + set_le32( h + 0x04, header_size - 8 + ds ); 1.139 + h [0x16] = chan_count; 1.140 + set_le32( h + 0x18, sample_rate_ ); 1.141 + set_le32( h + 0x1C, sample_rate_ * frame_size ); 1.142 + h [0x20] = frame_size; 1.143 + set_le32( h + 0x28, ds ); 1.144 + 1.145 + flush_(); 1.146 + 1.147 + /* write header */ 1.148 + fseek( file, 0, SEEK_SET ); 1.149 + fwrite( h, sizeof h, 1, file ); 1.150 + 1.151 + fclose( file ); 1.152 + file = 0; 1.153 + free( buf ); 1.154 + buf = 0; 1.155 + } 1.156 +}