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 +}