1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-10-10 16:43:33 +02:00

Converted CRLF to LF.

This commit is contained in:
lllucius
2013-11-01 23:22:33 +00:00
parent 43cb952167
commit f290b3d644
360 changed files with 62988 additions and 62988 deletions

View File

@@ -1,122 +1,122 @@
#include <math.h>
#include <string.h>
#include "biquad_filter.h"
/**
* Unit_BiquadFilter implements a second order IIR filter.
Here is the equation that we use for this filter:
y(n) = a0*x(n) + a1*x(n-1) + a2*x(n-2) - b1*y(n-1) - b2*y(n-2)
*
* @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved
*/
#define FILTER_PI (3.141592653589793238462643)
/***********************************************************
** Calculate coefficients common to many parametric biquad filters.
*/
static void BiquadFilter_CalculateCommon( BiquadFilter *filter, double ratio, double Q )
{
double omega;
memset( filter, 0, sizeof(BiquadFilter) );
/* Don't let frequency get too close to Nyquist or filter will blow up. */
if( ratio >= 0.499 ) ratio = 0.499;
omega = 2.0 * (double)FILTER_PI * ratio;
filter->cos_omega = (double) cos( omega );
filter->sin_omega = (double) sin( omega );
filter->alpha = filter->sin_omega / (2.0 * Q);
}
/*********************************************************************************
** Calculate coefficients for Highpass filter.
*/
void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q )
{
double scalar, opc;
if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO;
if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q;
BiquadFilter_CalculateCommon( filter, ratio, Q );
scalar = 1.0 / (1.0 + filter->alpha);
opc = (1.0 + filter->cos_omega);
filter->a0 = opc * 0.5 * scalar;
filter->a1 = - opc * scalar;
filter->a2 = filter->a0;
filter->b1 = -2.0 * filter->cos_omega * scalar;
filter->b2 = (1.0 - filter->alpha) * scalar;
}
/*********************************************************************************
** Calculate coefficients for Notch filter.
*/
void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q )
{
double scalar, opc;
if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO;
if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q;
BiquadFilter_CalculateCommon( filter, ratio, Q );
scalar = 1.0 / (1.0 + filter->alpha);
opc = (1.0 + filter->cos_omega);
filter->a0 = scalar;
filter->a1 = -2.0 * filter->cos_omega * scalar;
filter->a2 = filter->a0;
filter->b1 = filter->a1;
filter->b2 = (1.0 - filter->alpha) * scalar;
}
/*****************************************************************
** Perform core IIR filter calculation without permutation.
*/
void BiquadFilter_Filter( BiquadFilter *filter, float *inputs, float *outputs, int numSamples )
{
int i;
double xn, yn;
// Pull values from structure to speed up the calculation.
double a0 = filter->a0;
double a1 = filter->a1;
double a2 = filter->a2;
double b1 = filter->b1;
double b2 = filter->b2;
double xn1 = filter->xn1;
double xn2 = filter->xn2;
double yn1 = filter->yn1;
double yn2 = filter->yn2;
for( i=0; i<numSamples; i++)
{
// Generate outputs by filtering inputs.
xn = inputs[i];
yn = (a0 * xn) + (a1 * xn1) + (a2 * xn2) - (b1 * yn1) - (b2 * yn2);
outputs[i] = yn;
// Delay input and output values.
xn2 = xn1;
xn1 = xn;
yn2 = yn1;
yn1 = yn;
if( (i & 7) == 0 )
{
// Apply a small bipolar impulse to filter to prevent arithmetic underflow.
// Underflows can cause the FPU to interrupt the CPU.
yn1 += (double) 1.0E-26;
yn2 -= (double) 1.0E-26;
}
}
filter->xn1 = xn1;
filter->xn2 = xn2;
filter->yn1 = yn1;
filter->yn2 = yn2;
#include <math.h>
#include <string.h>
#include "biquad_filter.h"
/**
* Unit_BiquadFilter implements a second order IIR filter.
Here is the equation that we use for this filter:
y(n) = a0*x(n) + a1*x(n-1) + a2*x(n-2) - b1*y(n-1) - b2*y(n-2)
*
* @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved
*/
#define FILTER_PI (3.141592653589793238462643)
/***********************************************************
** Calculate coefficients common to many parametric biquad filters.
*/
static void BiquadFilter_CalculateCommon( BiquadFilter *filter, double ratio, double Q )
{
double omega;
memset( filter, 0, sizeof(BiquadFilter) );
/* Don't let frequency get too close to Nyquist or filter will blow up. */
if( ratio >= 0.499 ) ratio = 0.499;
omega = 2.0 * (double)FILTER_PI * ratio;
filter->cos_omega = (double) cos( omega );
filter->sin_omega = (double) sin( omega );
filter->alpha = filter->sin_omega / (2.0 * Q);
}
/*********************************************************************************
** Calculate coefficients for Highpass filter.
*/
void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q )
{
double scalar, opc;
if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO;
if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q;
BiquadFilter_CalculateCommon( filter, ratio, Q );
scalar = 1.0 / (1.0 + filter->alpha);
opc = (1.0 + filter->cos_omega);
filter->a0 = opc * 0.5 * scalar;
filter->a1 = - opc * scalar;
filter->a2 = filter->a0;
filter->b1 = -2.0 * filter->cos_omega * scalar;
filter->b2 = (1.0 - filter->alpha) * scalar;
}
/*********************************************************************************
** Calculate coefficients for Notch filter.
*/
void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q )
{
double scalar, opc;
if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO;
if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q;
BiquadFilter_CalculateCommon( filter, ratio, Q );
scalar = 1.0 / (1.0 + filter->alpha);
opc = (1.0 + filter->cos_omega);
filter->a0 = scalar;
filter->a1 = -2.0 * filter->cos_omega * scalar;
filter->a2 = filter->a0;
filter->b1 = filter->a1;
filter->b2 = (1.0 - filter->alpha) * scalar;
}
/*****************************************************************
** Perform core IIR filter calculation without permutation.
*/
void BiquadFilter_Filter( BiquadFilter *filter, float *inputs, float *outputs, int numSamples )
{
int i;
double xn, yn;
// Pull values from structure to speed up the calculation.
double a0 = filter->a0;
double a1 = filter->a1;
double a2 = filter->a2;
double b1 = filter->b1;
double b2 = filter->b2;
double xn1 = filter->xn1;
double xn2 = filter->xn2;
double yn1 = filter->yn1;
double yn2 = filter->yn2;
for( i=0; i<numSamples; i++)
{
// Generate outputs by filtering inputs.
xn = inputs[i];
yn = (a0 * xn) + (a1 * xn1) + (a2 * xn2) - (b1 * yn1) - (b2 * yn2);
outputs[i] = yn;
// Delay input and output values.
xn2 = xn1;
xn1 = xn;
yn2 = yn1;
yn1 = yn;
if( (i & 7) == 0 )
{
// Apply a small bipolar impulse to filter to prevent arithmetic underflow.
// Underflows can cause the FPU to interrupt the CPU.
yn1 += (double) 1.0E-26;
yn2 -= (double) 1.0E-26;
}
}
filter->xn1 = xn1;
filter->xn2 = xn2;
filter->yn1 = yn1;
filter->yn2 = yn2;
}

View File

@@ -1,38 +1,38 @@
#ifndef _BIQUADFILTER_H
#define _BIQUADFILTER_H
/**
* Unit_BiquadFilter implements a second order IIR filter.
*
* @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved
*/
#define BIQUAD_MIN_RATIO (0.000001)
#define BIQUAD_MIN_Q (0.00001)
typedef struct BiquadFilter_s
{
double xn1; // storage for delayed signals
double xn2;
double yn1;
double yn2;
double a0; // coefficients
double a1;
double a2;
double b1;
double b2;
double cos_omega;
double sin_omega;
double alpha;
} BiquadFilter;
void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q );
void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q );
void BiquadFilter_Filter( BiquadFilter *filter, float *inputs, float *outputs, int numSamples );
#endif
#ifndef _BIQUADFILTER_H
#define _BIQUADFILTER_H
/**
* Unit_BiquadFilter implements a second order IIR filter.
*
* @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved
*/
#define BIQUAD_MIN_RATIO (0.000001)
#define BIQUAD_MIN_Q (0.00001)
typedef struct BiquadFilter_s
{
double xn1; // storage for delayed signals
double xn2;
double yn1;
double yn2;
double a0; // coefficients
double a1;
double a2;
double b1;
double b2;
double cos_omega;
double sin_omega;
double alpha;
} BiquadFilter;
void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q );
void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q );
void BiquadFilter_Filter( BiquadFilter *filter, float *inputs, float *outputs, int numSamples );
#endif

View File

@@ -1,74 +1,74 @@
/*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Copyright (c) 1999-2010 Phil Burk and Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#ifndef _QA_TOOLS_H
#define _QA_TOOLS_H
extern int g_testsPassed;
extern int g_testsFailed;
#define QA_ASSERT_TRUE( message, flag ) \
if( !(flag) ) \
{ \
printf( "%s:%d - ERROR - %s\n", __FILE__, __LINE__, message ); \
g_testsFailed++; \
goto error; \
} \
else g_testsPassed++;
#define QA_ASSERT_EQUALS( message, expected, actual ) \
if( ((expected) != (actual)) ) \
{ \
printf( "%s:%d - ERROR - %s, expected %d, got %d\n", __FILE__, __LINE__, message, expected, actual ); \
g_testsFailed++; \
goto error; \
} \
else g_testsPassed++;
#define QA_ASSERT_CLOSE( message, expected, actual, tolerance ) \
if (fabs((expected)-(actual))>(tolerance)) \
{ \
printf( "%s:%d - ERROR - %s, expected %f, got %f, tol=%f\n", __FILE__, __LINE__, message, ((double)(expected)), ((double)(actual)), ((double)(tolerance)) ); \
g_testsFailed++; \
goto error; \
} \
else g_testsPassed++;
#endif
/*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Copyright (c) 1999-2010 Phil Burk and Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#ifndef _QA_TOOLS_H
#define _QA_TOOLS_H
extern int g_testsPassed;
extern int g_testsFailed;
#define QA_ASSERT_TRUE( message, flag ) \
if( !(flag) ) \
{ \
printf( "%s:%d - ERROR - %s\n", __FILE__, __LINE__, message ); \
g_testsFailed++; \
goto error; \
} \
else g_testsPassed++;
#define QA_ASSERT_EQUALS( message, expected, actual ) \
if( ((expected) != (actual)) ) \
{ \
printf( "%s:%d - ERROR - %s, expected %d, got %d\n", __FILE__, __LINE__, message, expected, actual ); \
g_testsFailed++; \
goto error; \
} \
else g_testsPassed++;
#define QA_ASSERT_CLOSE( message, expected, actual, tolerance ) \
if (fabs((expected)-(actual))>(tolerance)) \
{ \
printf( "%s:%d - ERROR - %s, expected %f, got %f, tol=%f\n", __FILE__, __LINE__, message, ((double)(expected)), ((double)(actual)), ((double)(tolerance)) ); \
g_testsFailed++; \
goto error; \
} \
else g_testsPassed++;
#endif

View File

@@ -1,242 +1,242 @@
/*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Copyright (c) 1999-2010 Phil Burk and Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/**
* Very simple WAV file writer for saving captured audio.
*/
#include <stdio.h>
#include <stdlib.h>
#include "write_wav.h"
/* Write long word data to a little endian format byte array. */
static void WriteLongLE( unsigned char **addrPtr, unsigned long data )
{
unsigned char *addr = *addrPtr;
*addr++ = (unsigned char) data;
*addr++ = (unsigned char) (data>>8);
*addr++ = (unsigned char) (data>>16);
*addr++ = (unsigned char) (data>>24);
*addrPtr = addr;
}
/* Write short word data to a little endian format byte array. */
static void WriteShortLE( unsigned char **addrPtr, unsigned short data )
{
unsigned char *addr = *addrPtr;
*addr++ = (unsigned char) data;
*addr++ = (unsigned char) (data>>8);
*addrPtr = addr;
}
/* Write IFF ChunkType data to a byte array. */
static void WriteChunkType( unsigned char **addrPtr, unsigned long cktyp )
{
unsigned char *addr = *addrPtr;
*addr++ = (unsigned char) (cktyp>>24);
*addr++ = (unsigned char) (cktyp>>16);
*addr++ = (unsigned char) (cktyp>>8);
*addr++ = (unsigned char) cktyp;
*addrPtr = addr;
}
#define WAV_HEADER_SIZE (4 + 4 + 4 + /* RIFF+size+WAVE */ \
4 + 4 + 16 + /* fmt chunk */ \
4 + 4 ) /* data chunk */
/*********************************************************************************
* Open named file and write WAV header to the file.
* The header includes the DATA chunk type and size.
* Returns number of bytes written to file or negative error code.
*/
long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame )
{
unsigned int bytesPerSecond;
unsigned char header[ WAV_HEADER_SIZE ];
unsigned char *addr = header;
int numWritten;
writer->dataSize = 0;
writer->dataSizeOffset = 0;
writer->fid = fopen( fileName, "wb" );
if( writer->fid == NULL )
{
return -1;
}
/* Write RIFF header. */
WriteChunkType( &addr, RIFF_ID );
/* Write RIFF size as zero for now. Will patch later. */
WriteLongLE( &addr, 0 );
/* Write WAVE form ID. */
WriteChunkType( &addr, WAVE_ID );
/* Write format chunk based on AudioSample structure. */
WriteChunkType( &addr, FMT_ID );
WriteLongLE( &addr, 16 );
WriteShortLE( &addr, WAVE_FORMAT_PCM );
bytesPerSecond = frameRate * samplesPerFrame * sizeof( short);
WriteShortLE( &addr, (short) samplesPerFrame );
WriteLongLE( &addr, frameRate );
WriteLongLE( &addr, bytesPerSecond );
WriteShortLE( &addr, (short) (samplesPerFrame * sizeof( short)) ); /* bytesPerBlock */
WriteShortLE( &addr, (short) 16 ); /* bits per sample */
/* Write ID and size for 'data' chunk. */
WriteChunkType( &addr, DATA_ID );
/* Save offset so we can patch it later. */
writer->dataSizeOffset = (int) (addr - header);
WriteLongLE( &addr, 0 );
numWritten = fwrite( header, 1, sizeof(header), writer->fid );
if( numWritten != sizeof(header) ) return -1;
return (int) numWritten;
}
/*********************************************************************************
* Write to the data chunk portion of a WAV file.
* Returns bytes written or negative error code.
*/
long Audio_WAV_WriteShorts( WAV_Writer *writer,
short *samples,
int numSamples
)
{
unsigned char buffer[2];
unsigned char *bufferPtr;
int i;
short *p = samples;
int numWritten;
int bytesWritten;
if( numSamples <= 0 )
{
return -1;
}
for( i=0; i<numSamples; i++ )
{
bufferPtr = buffer;
WriteShortLE( &bufferPtr, *p++ );
numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
if( numWritten != sizeof(buffer) ) return -1;
}
bytesWritten = numSamples * sizeof(short);
writer->dataSize += bytesWritten;
return (int) bytesWritten;
}
/*********************************************************************************
* Close WAV file.
* Update chunk sizes so it can be read by audio applications.
*/
long Audio_WAV_CloseWriter( WAV_Writer *writer )
{
unsigned char buffer[4];
unsigned char *bufferPtr;
int numWritten;
int riffSize;
/* Go back to beginning of file and update DATA size */
int result = fseek( writer->fid, writer->dataSizeOffset, SEEK_SET );
if( result < 0 ) return result;
bufferPtr = buffer;
WriteLongLE( &bufferPtr, writer->dataSize );
numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
if( numWritten != sizeof(buffer) ) return -1;
/* Update RIFF size */
result = fseek( writer->fid, 4, SEEK_SET );
if( result < 0 ) return result;
riffSize = writer->dataSize + (WAV_HEADER_SIZE - 8);
bufferPtr = buffer;
WriteLongLE( &bufferPtr, riffSize );
numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
if( numWritten != sizeof(buffer) ) return -1;
fclose( writer->fid );
writer->fid = NULL;
return writer->dataSize;
}
/*********************************************************************************
* Simple test that write a sawtooth waveform to a file.
*/
#if 0
int main( void )
{
int i;
WAV_Writer writer;
int result;
#define NUM_SAMPLES (200)
short data[NUM_SAMPLES];
short saw = 0;
for( i=0; i<NUM_SAMPLES; i++ )
{
data[i] = saw;
saw += 293;
}
result = Audio_WAV_OpenWriter( &writer, "rendered_midi.wav", 44100, 1 );
if( result < 0 ) goto error;
for( i=0; i<15; i++ )
{
result = Audio_WAV_WriteShorts( &writer, data, NUM_SAMPLES );
if( result < 0 ) goto error;
}
result = Audio_WAV_CloseWriter( &writer );
if( result < 0 ) goto error;
return 0;
error:
printf("ERROR: result = %d\n", result );
return result;
}
#endif
/*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Copyright (c) 1999-2010 Phil Burk and Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/**
* Very simple WAV file writer for saving captured audio.
*/
#include <stdio.h>
#include <stdlib.h>
#include "write_wav.h"
/* Write long word data to a little endian format byte array. */
static void WriteLongLE( unsigned char **addrPtr, unsigned long data )
{
unsigned char *addr = *addrPtr;
*addr++ = (unsigned char) data;
*addr++ = (unsigned char) (data>>8);
*addr++ = (unsigned char) (data>>16);
*addr++ = (unsigned char) (data>>24);
*addrPtr = addr;
}
/* Write short word data to a little endian format byte array. */
static void WriteShortLE( unsigned char **addrPtr, unsigned short data )
{
unsigned char *addr = *addrPtr;
*addr++ = (unsigned char) data;
*addr++ = (unsigned char) (data>>8);
*addrPtr = addr;
}
/* Write IFF ChunkType data to a byte array. */
static void WriteChunkType( unsigned char **addrPtr, unsigned long cktyp )
{
unsigned char *addr = *addrPtr;
*addr++ = (unsigned char) (cktyp>>24);
*addr++ = (unsigned char) (cktyp>>16);
*addr++ = (unsigned char) (cktyp>>8);
*addr++ = (unsigned char) cktyp;
*addrPtr = addr;
}
#define WAV_HEADER_SIZE (4 + 4 + 4 + /* RIFF+size+WAVE */ \
4 + 4 + 16 + /* fmt chunk */ \
4 + 4 ) /* data chunk */
/*********************************************************************************
* Open named file and write WAV header to the file.
* The header includes the DATA chunk type and size.
* Returns number of bytes written to file or negative error code.
*/
long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame )
{
unsigned int bytesPerSecond;
unsigned char header[ WAV_HEADER_SIZE ];
unsigned char *addr = header;
int numWritten;
writer->dataSize = 0;
writer->dataSizeOffset = 0;
writer->fid = fopen( fileName, "wb" );
if( writer->fid == NULL )
{
return -1;
}
/* Write RIFF header. */
WriteChunkType( &addr, RIFF_ID );
/* Write RIFF size as zero for now. Will patch later. */
WriteLongLE( &addr, 0 );
/* Write WAVE form ID. */
WriteChunkType( &addr, WAVE_ID );
/* Write format chunk based on AudioSample structure. */
WriteChunkType( &addr, FMT_ID );
WriteLongLE( &addr, 16 );
WriteShortLE( &addr, WAVE_FORMAT_PCM );
bytesPerSecond = frameRate * samplesPerFrame * sizeof( short);
WriteShortLE( &addr, (short) samplesPerFrame );
WriteLongLE( &addr, frameRate );
WriteLongLE( &addr, bytesPerSecond );
WriteShortLE( &addr, (short) (samplesPerFrame * sizeof( short)) ); /* bytesPerBlock */
WriteShortLE( &addr, (short) 16 ); /* bits per sample */
/* Write ID and size for 'data' chunk. */
WriteChunkType( &addr, DATA_ID );
/* Save offset so we can patch it later. */
writer->dataSizeOffset = (int) (addr - header);
WriteLongLE( &addr, 0 );
numWritten = fwrite( header, 1, sizeof(header), writer->fid );
if( numWritten != sizeof(header) ) return -1;
return (int) numWritten;
}
/*********************************************************************************
* Write to the data chunk portion of a WAV file.
* Returns bytes written or negative error code.
*/
long Audio_WAV_WriteShorts( WAV_Writer *writer,
short *samples,
int numSamples
)
{
unsigned char buffer[2];
unsigned char *bufferPtr;
int i;
short *p = samples;
int numWritten;
int bytesWritten;
if( numSamples <= 0 )
{
return -1;
}
for( i=0; i<numSamples; i++ )
{
bufferPtr = buffer;
WriteShortLE( &bufferPtr, *p++ );
numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
if( numWritten != sizeof(buffer) ) return -1;
}
bytesWritten = numSamples * sizeof(short);
writer->dataSize += bytesWritten;
return (int) bytesWritten;
}
/*********************************************************************************
* Close WAV file.
* Update chunk sizes so it can be read by audio applications.
*/
long Audio_WAV_CloseWriter( WAV_Writer *writer )
{
unsigned char buffer[4];
unsigned char *bufferPtr;
int numWritten;
int riffSize;
/* Go back to beginning of file and update DATA size */
int result = fseek( writer->fid, writer->dataSizeOffset, SEEK_SET );
if( result < 0 ) return result;
bufferPtr = buffer;
WriteLongLE( &bufferPtr, writer->dataSize );
numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
if( numWritten != sizeof(buffer) ) return -1;
/* Update RIFF size */
result = fseek( writer->fid, 4, SEEK_SET );
if( result < 0 ) return result;
riffSize = writer->dataSize + (WAV_HEADER_SIZE - 8);
bufferPtr = buffer;
WriteLongLE( &bufferPtr, riffSize );
numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
if( numWritten != sizeof(buffer) ) return -1;
fclose( writer->fid );
writer->fid = NULL;
return writer->dataSize;
}
/*********************************************************************************
* Simple test that write a sawtooth waveform to a file.
*/
#if 0
int main( void )
{
int i;
WAV_Writer writer;
int result;
#define NUM_SAMPLES (200)
short data[NUM_SAMPLES];
short saw = 0;
for( i=0; i<NUM_SAMPLES; i++ )
{
data[i] = saw;
saw += 293;
}
result = Audio_WAV_OpenWriter( &writer, "rendered_midi.wav", 44100, 1 );
if( result < 0 ) goto error;
for( i=0; i<15; i++ )
{
result = Audio_WAV_WriteShorts( &writer, data, NUM_SAMPLES );
if( result < 0 ) goto error;
}
result = Audio_WAV_CloseWriter( &writer );
if( result < 0 ) goto error;
return 0;
error:
printf("ERROR: result = %d\n", result );
return result;
}
#endif

View File

@@ -1,103 +1,103 @@
/*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Copyright (c) 1999-2010 Phil Burk and Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#ifndef _WAV_WRITER_H
#define _WAV_WRITER_H
/*
* WAV file writer.
*
* Author: Phil Burk
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Define WAV Chunk and FORM types as 4 byte integers. */
#define RIFF_ID (('R'<<24) | ('I'<<16) | ('F'<<8) | 'F')
#define WAVE_ID (('W'<<24) | ('A'<<16) | ('V'<<8) | 'E')
#define FMT_ID (('f'<<24) | ('m'<<16) | ('t'<<8) | ' ')
#define DATA_ID (('d'<<24) | ('a'<<16) | ('t'<<8) | 'a')
#define FACT_ID (('f'<<24) | ('a'<<16) | ('c'<<8) | 't')
/* Errors returned by Audio_ParseSampleImage_WAV */
#define WAV_ERR_CHUNK_SIZE (-1) /* Chunk size is illegal or past file size. */
#define WAV_ERR_FILE_TYPE (-2) /* Not a WAV file. */
#define WAV_ERR_ILLEGAL_VALUE (-3) /* Illegal or unsupported value. Eg. 927 bits/sample */
#define WAV_ERR_FORMAT_TYPE (-4) /* Unsupported format, eg. compressed. */
#define WAV_ERR_TRUNCATED (-5) /* End of file missing. */
/* WAV PCM data format ID */
#define WAVE_FORMAT_PCM (1)
#define WAVE_FORMAT_IMA_ADPCM (0x0011)
typedef struct WAV_Writer_s
{
FILE *fid;
/* Offset in file for data size. */
int dataSizeOffset;
int dataSize;
} WAV_Writer;
/*********************************************************************************
* Open named file and write WAV header to the file.
* The header includes the DATA chunk type and size.
* Returns number of bytes written to file or negative error code.
*/
long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame );
/*********************************************************************************
* Write to the data chunk portion of a WAV file.
* Returns bytes written or negative error code.
*/
long Audio_WAV_WriteShorts( WAV_Writer *writer,
short *samples,
int numSamples
);
/*********************************************************************************
* Close WAV file.
* Update chunk sizes so it can be read by audio applications.
*/
long Audio_WAV_CloseWriter( WAV_Writer *writer );
#ifdef __cplusplus
};
#endif
#endif /* _WAV_WRITER_H */
/*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Copyright (c) 1999-2010 Phil Burk and Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#ifndef _WAV_WRITER_H
#define _WAV_WRITER_H
/*
* WAV file writer.
*
* Author: Phil Burk
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Define WAV Chunk and FORM types as 4 byte integers. */
#define RIFF_ID (('R'<<24) | ('I'<<16) | ('F'<<8) | 'F')
#define WAVE_ID (('W'<<24) | ('A'<<16) | ('V'<<8) | 'E')
#define FMT_ID (('f'<<24) | ('m'<<16) | ('t'<<8) | ' ')
#define DATA_ID (('d'<<24) | ('a'<<16) | ('t'<<8) | 'a')
#define FACT_ID (('f'<<24) | ('a'<<16) | ('c'<<8) | 't')
/* Errors returned by Audio_ParseSampleImage_WAV */
#define WAV_ERR_CHUNK_SIZE (-1) /* Chunk size is illegal or past file size. */
#define WAV_ERR_FILE_TYPE (-2) /* Not a WAV file. */
#define WAV_ERR_ILLEGAL_VALUE (-3) /* Illegal or unsupported value. Eg. 927 bits/sample */
#define WAV_ERR_FORMAT_TYPE (-4) /* Unsupported format, eg. compressed. */
#define WAV_ERR_TRUNCATED (-5) /* End of file missing. */
/* WAV PCM data format ID */
#define WAVE_FORMAT_PCM (1)
#define WAVE_FORMAT_IMA_ADPCM (0x0011)
typedef struct WAV_Writer_s
{
FILE *fid;
/* Offset in file for data size. */
int dataSizeOffset;
int dataSize;
} WAV_Writer;
/*********************************************************************************
* Open named file and write WAV header to the file.
* The header includes the DATA chunk type and size.
* Returns number of bytes written to file or negative error code.
*/
long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame );
/*********************************************************************************
* Write to the data chunk portion of a WAV file.
* Returns bytes written or negative error code.
*/
long Audio_WAV_WriteShorts( WAV_Writer *writer,
short *samples,
int numSamples
);
/*********************************************************************************
* Close WAV file.
* Update chunk sizes so it can be read by audio applications.
*/
long Audio_WAV_CloseWriter( WAV_Writer *writer );
#ifdef __cplusplus
};
#endif
#endif /* _WAV_WRITER_H */