To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / portaudio_20161030_catalina_patch / qa / loopback / src / write_wav.c @ 164:9fa11135915a

History | View | Annotate | Download (7.18 KB)

1
/*
2
 * PortAudio Portable Real-Time Audio Library
3
 * Latest Version at: http://www.portaudio.com
4
 *
5
 * Copyright (c) 1999-2010 Phil Burk and Ross Bencina
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files
9
 * (the "Software"), to deal in the Software without restriction,
10
 * including without limitation the rights to use, copy, modify, merge,
11
 * publish, distribute, sublicense, and/or sell copies of the Software,
12
 * and to permit persons to whom the Software is furnished to do so,
13
 * subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26

    
27
/*
28
 * The text above constitutes the entire PortAudio license; however, 
29
 * the PortAudio community also makes the following non-binding requests:
30
 *
31
 * Any person wishing to distribute modifications to the Software is
32
 * requested to send the modifications to the original developer so that
33
 * they can be incorporated into the canonical version. It is also 
34
 * requested that these non-binding requests be included along with the 
35
 * license above.
36
 */
37

    
38
/**
39
  * Very simple WAV file writer for saving captured audio.
40
  */
41

    
42
#include <stdio.h>
43
#include <stdlib.h>
44
#include "write_wav.h"
45

    
46

    
47
/* Write long word data to a little endian format byte array. */
48
static void WriteLongLE( unsigned char **addrPtr, unsigned long data )
49
{
50
        unsigned char *addr = *addrPtr;
51
        *addr++ =  (unsigned char) data;
52
        *addr++ =  (unsigned char) (data>>8);
53
        *addr++ =  (unsigned char) (data>>16);
54
        *addr++ =  (unsigned char) (data>>24);
55
        *addrPtr = addr;
56
}
57

    
58
/* Write short word data to a little endian format byte array. */
59
static void WriteShortLE( unsigned char **addrPtr,  unsigned short data )
60
{
61
        unsigned char *addr = *addrPtr;
62
        *addr++ =  (unsigned char) data;
63
        *addr++ =  (unsigned char) (data>>8);
64
        *addrPtr = addr;
65
}
66

    
67
/* Write IFF ChunkType data to a byte array. */
68
static void WriteChunkType( unsigned char **addrPtr, unsigned long cktyp )
69
{
70
        unsigned char *addr = *addrPtr;
71
        *addr++ =  (unsigned char) (cktyp>>24);
72
        *addr++ =  (unsigned char) (cktyp>>16);
73
        *addr++ =  (unsigned char) (cktyp>>8);
74
        *addr++ =  (unsigned char) cktyp;
75
        *addrPtr = addr;
76
}
77

    
78
#define WAV_HEADER_SIZE (4 + 4 + 4 + /* RIFF+size+WAVE */ \
79
        4 + 4 + 16 + /* fmt chunk */ \
80
        4 + 4 ) /* data chunk */
81

    
82

    
83
/*********************************************************************************
84
 * Open named file and write WAV header to the file.
85
 * The header includes the DATA chunk type and size.
86
 * Returns number of bytes written to file or negative error code.
87
 */
88
long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame )
89
{
90
        unsigned int  bytesPerSecond;
91
    unsigned char header[ WAV_HEADER_SIZE ];
92
        unsigned char *addr = header;
93
    int numWritten;
94
        
95
    writer->dataSize = 0;
96
    writer->dataSizeOffset = 0;
97
        
98
    writer->fid = fopen( fileName, "wb" );
99
    if( writer->fid == NULL )
100
    {
101
        return -1;
102
    }
103

    
104
/* Write RIFF header. */
105
        WriteChunkType( &addr, RIFF_ID );
106

    
107
/* Write RIFF size as zero for now. Will patch later. */
108
        WriteLongLE( &addr, 0 );
109

    
110
/* Write WAVE form ID. */
111
        WriteChunkType( &addr, WAVE_ID );
112

    
113
/* Write format chunk based on AudioSample structure. */
114
        WriteChunkType( &addr, FMT_ID );
115
    WriteLongLE( &addr, 16 );
116
    WriteShortLE( &addr, WAVE_FORMAT_PCM );
117
                bytesPerSecond = frameRate * samplesPerFrame * sizeof( short);
118
        WriteShortLE( &addr, (short) samplesPerFrame );
119
        WriteLongLE( &addr, frameRate );
120
        WriteLongLE( &addr,  bytesPerSecond );
121
        WriteShortLE( &addr, (short) (samplesPerFrame * sizeof( short)) ); /* bytesPerBlock */
122
        WriteShortLE( &addr, (short) 16 ); /* bits per sample */
123

    
124
/* Write ID and size for 'data' chunk. */
125
        WriteChunkType( &addr, DATA_ID );
126
/* Save offset so we can patch it later. */
127
    writer->dataSizeOffset = (int) (addr - header);
128
        WriteLongLE( &addr, 0 );
129

    
130
    numWritten = fwrite( header, 1, sizeof(header), writer->fid );
131
    if( numWritten != sizeof(header) ) return -1;
132

    
133
        return (int) numWritten;
134
}
135

    
136
/*********************************************************************************
137
 * Write to the data chunk portion of a WAV file.
138
 * Returns bytes written or negative error code.
139
 */
140
long Audio_WAV_WriteShorts( WAV_Writer *writer,
141
                short *samples,
142
                int numSamples
143
                )
144
{
145
        unsigned char buffer[2];
146
    unsigned char *bufferPtr;
147
        int i;
148
        short *p = samples;
149
    int numWritten;
150
    int bytesWritten;
151
        if( numSamples <= 0 )
152
        {
153
                return -1;
154
        }
155

    
156
    for( i=0; i<numSamples; i++ )
157
        {
158
        bufferPtr = buffer;
159
                WriteShortLE( &bufferPtr, *p++ );
160
        numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
161
        if( numWritten != sizeof(buffer) ) return -1;
162
        }
163
    bytesWritten = numSamples * sizeof(short);
164
    writer->dataSize += bytesWritten;
165
        return (int) bytesWritten;
166
}
167

    
168
/*********************************************************************************
169
 * Close WAV file.
170
 * Update chunk sizes so it can be read by audio applications.
171
 */
172
long Audio_WAV_CloseWriter( WAV_Writer *writer )
173
{
174
        unsigned char buffer[4];
175
    unsigned char *bufferPtr;
176
    int numWritten;
177
    int riffSize;
178

    
179
    /* Go back to beginning of file and update DATA size */
180
    int result = fseek( writer->fid, writer->dataSizeOffset, SEEK_SET );
181
    if( result < 0 ) return result;
182

    
183
    bufferPtr = buffer;
184
    WriteLongLE( &bufferPtr, writer->dataSize );
185
    numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
186
    if( numWritten != sizeof(buffer) ) return -1;
187

    
188
    /* Update RIFF size */
189
    result = fseek( writer->fid, 4, SEEK_SET );
190
    if( result < 0 ) return result;
191

    
192
    riffSize = writer->dataSize + (WAV_HEADER_SIZE - 8);
193
    bufferPtr = buffer;
194
    WriteLongLE( &bufferPtr, riffSize );
195
    numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid );
196
    if( numWritten != sizeof(buffer) ) return -1;
197

    
198
    fclose( writer->fid );
199
    writer->fid = NULL;
200
    return writer->dataSize;
201
}
202

    
203
/*********************************************************************************
204
 * Simple test that write a sawtooth waveform to a file.
205
 */
206
#if 0
207
int main( void )
208
{
209
    int i;
210
    WAV_Writer writer;
211
    int result;
212
#define NUM_SAMPLES  (200)
213
    short data[NUM_SAMPLES];
214
    short saw = 0;
215
    
216
    for( i=0; i<NUM_SAMPLES; i++ )
217
    {
218
        data[i] = saw;
219
        saw += 293;
220
    }
221

222

223
    result =  Audio_WAV_OpenWriter( &writer, "rendered_midi.wav", 44100, 1 );
224
    if( result < 0 ) goto error;
225

226
    for( i=0; i<15; i++ )
227
    {
228
        result =  Audio_WAV_WriteShorts( &writer, data, NUM_SAMPLES );
229
        if( result < 0 ) goto error;
230
    }
231

232
    result =  Audio_WAV_CloseWriter( &writer );
233
    if( result < 0 ) goto error;
234

235

236
    return 0;
237

238
error:
239
    printf("ERROR: result = %d\n", result );
240
    return result;
241
}
242
#endif