Mercurial > spc_convert
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e38dacceb958 |
---|---|
1 /* snes_spc 0.9.0. http://www.slack.net/~ant/ */ | |
2 | |
3 #include "wave_writer.h" | |
4 | |
5 #include <assert.h> | |
6 #include <stdlib.h> | |
7 #include <stdio.h> | |
8 | |
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 */ | |
19 | |
20 enum { buf_size = 32768 * 2 }; | |
21 enum { header_size = 0x2C }; | |
22 | |
23 typedef short sample_t; | |
24 | |
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; | |
31 | |
32 static void exit_with_error( const char* str ) | |
33 { | |
34 printf( "Error: %s\n", str ); getchar(); | |
35 exit( EXIT_FAILURE ); | |
36 } | |
37 | |
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; | |
44 | |
45 buf = (unsigned char*) malloc( buf_size * sizeof *buf ); | |
46 if ( !buf ) | |
47 exit_with_error( "Out of memory" ); | |
48 | |
49 file = fopen( filename, "wb" ); | |
50 if ( !file ) | |
51 exit_with_error( "Couldn't open WAVE file for writing" ); | |
52 | |
53 setvbuf( file, 0, _IOFBF, 32 * 1024L ); | |
54 } | |
55 | |
56 void wave_enable_stereo( void ) | |
57 { | |
58 chan_count = 2; | |
59 } | |
60 | |
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 } | |
67 | |
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_(); | |
75 | |
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; | |
82 | |
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 } | |
90 | |
91 buf_pos = p - buf; | |
92 assert( buf_pos <= buf_size ); | |
93 } | |
94 } | |
95 } | |
96 | |
97 long wave_sample_count( void ) | |
98 { | |
99 return sample_count_; | |
100 } | |
101 | |
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 } | |
109 | |
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); | |
134 | |
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 ); | |
141 | |
142 flush_(); | |
143 | |
144 /* write header */ | |
145 fseek( file, 0, SEEK_SET ); | |
146 fwrite( h, sizeof h, 1, file ); | |
147 | |
148 fclose( file ); | |
149 file = 0; | |
150 free( buf ); | |
151 buf = 0; | |
152 } | |
153 } |