• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Based on the WaveFileWriter in Java from the open source JSyn library by Phil Burk
18 // https://github.com/philburk/jsyn/blob/master/src/com/jsyn/util/WaveFileWriter.java
19 
20 #ifndef UTIL_WAVE_FILE_WRITER
21 #define UTIL_WAVE_FILE_WRITER
22 
23 #include <cassert>
24 #include <stdio.h>
25 
26 class WaveFileOutputStream {
27 public:
28     virtual void write(uint8_t b) = 0;
29 };
30 
31 /**
32  * Write audio data to a WAV file.
33  *
34  * <pre>
35  * <code>
36  * WaveFileWriter writer = new WaveFileWriter(waveFileOutputStream);
37  * writer.setFrameRate(48000);
38  * writer.setBitsPerSample(24);
39  * writer.write(floatArray, 0, numSamples);
40  * writer.close();
41  * </code>
42  * </pre>
43  *
44  */
45 class WaveFileWriter {
46 public:
47 
48     /**
49      * Create an object that will write a WAV file image to the specified stream.
50      *
51      * @param outputStream stream to receive the bytes
52      * @throws FileNotFoundException
53      */
WaveFileWriter(WaveFileOutputStream * outputStream)54     WaveFileWriter(WaveFileOutputStream *outputStream) {
55         mOutputStream = outputStream;
56     }
57 
58     /**
59      * @param frameRate default is 44100
60      */
setFrameRate(int32_t frameRate)61     void setFrameRate(int32_t frameRate) {
62         mFrameRate = frameRate;
63     }
64 
getFrameRate()65     int32_t getFrameRate() const {
66         return mFrameRate;
67     }
68 
69     /**
70      * For stereo, set this to 2. Default is mono = 1.
71      * Also known as ChannelCount
72      */
setSamplesPerFrame(int32_t samplesPerFrame)73     void setSamplesPerFrame(int32_t samplesPerFrame) {
74         mSamplesPerFrame = samplesPerFrame;
75     }
76 
getSamplesPerFrame()77     int32_t getSamplesPerFrame() const {
78         return mSamplesPerFrame;
79     }
80 
81     /** Only 16 or 24 bit samples supported at the moment. Default is 16. */
setBitsPerSample(int32_t bits)82     void setBitsPerSample(int32_t bits) {
83         assert((bits == 16) || (bits == 24));
84         bitsPerSample = bits;
85     }
86 
getBitsPerSample()87     int32_t getBitsPerSample() const {
88         return bitsPerSample;
89     }
90 
close()91     void close() {
92     }
93 
94     /** Write single audio data value to the WAV file. */
95     void write(float value);
96 
97     /**
98      * Write a buffer to the WAV file.
99      */
100     void write(float *buffer, int32_t startSample, int32_t numSamples);
101 
102 private:
103     /**
104      * Write a 32 bit integer to the stream in Little Endian format.
105      */
106     void writeIntLittle(int32_t n);
107 
108     /**
109      * Write a 16 bit integer to the stream in Little Endian format.
110      */
111     void writeShortLittle(int16_t n);
112 
113     /**
114      * Write an 'fmt ' chunk to the WAV file containing the given information.
115      */
116     void writeFormatChunk();
117 
118     /**
119      * Write a 'data' chunk header to the WAV file. This should be followed by call to
120      * writeShortLittle() to write the data to the chunk.
121      */
122     void writeDataChunkHeader();
123 
124     /**
125      * Write a simple WAV header for PCM data.
126      */
127     void writeHeader();
128 
129     // Write lower 8 bits. Upper bits ignored.
130     void writeByte(uint8_t b);
131 
132     void writePCM24(float value);
133 
134     void writePCM16(float value);
135 
136     /**
137      * Write a 'RIFF' file header and a 'WAVE' ID to the WAV file.
138      */
139     void writeRiffHeader();
140 
141     static constexpr int WAVE_FORMAT_PCM = 1;
142     WaveFileOutputStream *mOutputStream = nullptr;
143     int32_t mFrameRate = 48000;
144     int32_t mSamplesPerFrame = 1;
145     int32_t bitsPerSample = 16;
146     int32_t bytesWritten = 0;
147     bool headerWritten = false;
148     static constexpr int32_t PCM24_MIN = -(1 << 23);
149     static constexpr int32_t PCM24_MAX = (1 << 23) - 1;
150 
151 };
152 
153 #endif /* UTIL_WAVE_FILE_WRITER */
154 
155