view 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 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; you
10 can redistribute it and/or modify it under the terms of the GNU Lesser
11 General Public License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version. This
13 module is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16 details. You should have received a copy of the GNU Lesser General Public
17 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 }