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