Mercurial > spc_convert
view demo/wave_writer.c @ 6:a012d31df380
Made convert.pl work in parallel. Restored files in less than 2 minutes!
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 21 Oct 2011 07:23:22 -0700 |
parents | e38dacceb958 |
children |
line wrap: on
line source
1 /* snes_spc 0.9.0. http://www.slack.net/~ant/ */3 #include "wave_writer.h"5 #include <assert.h>6 #include <stdlib.h>7 #include <stdio.h>9 /* Copyright (C) 2003-2007 Shay Green. This module is free software; you10 can redistribute it and/or modify it under the terms of the GNU Lesser11 General Public License as published by the Free Software Foundation; either12 version 2.1 of the License, or (at your option) any later version. This13 module is distributed in the hope that it will be useful, but WITHOUT ANY14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more16 details. You should have received a copy of the GNU Lesser General Public17 License along with this module; if not, write to the Free Software Foundation,18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */20 enum { buf_size = 32768 * 2 };21 enum { header_size = 0x2C };23 typedef short sample_t;25 static unsigned char* buf;26 static FILE* file;27 static long sample_count_;28 static long sample_rate_;29 static long buf_pos;30 static int chan_count;32 static void exit_with_error( const char* str )33 {34 printf( "Error: %s\n", str ); getchar();35 exit( EXIT_FAILURE );36 }38 void wave_open( long sample_rate, const char* filename )39 {40 sample_count_ = 0;41 sample_rate_ = sample_rate;42 buf_pos = header_size;43 chan_count = 1;45 buf = (unsigned char*) malloc( buf_size * sizeof *buf );46 if ( !buf )47 exit_with_error( "Out of memory" );49 file = fopen( filename, "wb" );50 if ( !file )51 exit_with_error( "Couldn't open WAVE file for writing" );53 setvbuf( file, 0, _IOFBF, 32 * 1024L );54 }56 void wave_enable_stereo( void )57 {58 chan_count = 2;59 }61 static void flush_()62 {63 if ( buf_pos && !fwrite( buf, buf_pos, 1, file ) )64 exit_with_error( "Couldn't write WAVE data" );65 buf_pos = 0;66 }68 void wave_write( short const* in, long remain )69 {70 sample_count_ += remain;71 while ( remain )72 {73 if ( buf_pos >= buf_size )74 flush_();76 {77 unsigned char* p = &buf [buf_pos];78 long n = (buf_size - buf_pos) / sizeof (sample_t);79 if ( n > remain )80 n = remain;81 remain -= n;83 /* convert to LSB first format */84 while ( n-- )85 {86 int s = *in++;87 *p++ = (unsigned char) s;88 *p++ = (unsigned char) (s >> 8);89 }91 buf_pos = p - buf;92 assert( buf_pos <= buf_size );93 }94 }95 }97 long wave_sample_count( void )98 {99 return sample_count_;100 }102 static void set_le32( void* p, unsigned long n )103 {104 ((unsigned char*) p) [0] = (unsigned char) n;105 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);106 ((unsigned char*) p) [2] = (unsigned char) (n >> 16);107 ((unsigned char*) p) [3] = (unsigned char) (n >> 24);108 }110 void wave_close( void )111 {112 if ( file )113 {114 /* generate header */115 unsigned char h [header_size] =116 {117 'R','I','F','F',118 0,0,0,0, /* length of rest of file */119 'W','A','V','E',120 'f','m','t',' ',121 0x10,0,0,0, /* size of fmt chunk */122 1,0, /* uncompressed format */123 0,0, /* channel count */124 0,0,0,0, /* sample rate */125 0,0,0,0, /* bytes per second */126 0,0, /* bytes per sample frame */127 16,0, /* bits per sample */128 'd','a','t','a',129 0,0,0,0, /* size of sample data */130 /* ... */ /* sample data */131 };132 long ds = sample_count_ * sizeof (sample_t);133 int frame_size = chan_count * sizeof (sample_t);135 set_le32( h + 0x04, header_size - 8 + ds );136 h [0x16] = chan_count;137 set_le32( h + 0x18, sample_rate_ );138 set_le32( h + 0x1C, sample_rate_ * frame_size );139 h [0x20] = frame_size;140 set_le32( h + 0x28, ds );142 flush_();144 /* write header */145 fseek( file, 0, SEEK_SET );146 fwrite( h, sizeof h, 1, file );148 fclose( file );149 file = 0;150 free( buf );151 buf = 0;152 }153 }