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