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 #include "WaveFileWriter.h" 18 write(float value)19void WaveFileWriter::WaveFileWriter::write(float value) { 20 if (!mHeaderWritten) { 21 writeHeader(); 22 } 23 if (mBitsPerSample == 24) { 24 writePCM24(value); 25 } else { 26 writePCM16(value); 27 } 28 } 29 write(float * buffer,int32_t startSample,int32_t numSamples)30void WaveFileWriter::write(float *buffer, int32_t startSample, int32_t numSamples) { 31 for (int32_t i = 0; i < numSamples; i++) { 32 write(buffer[startSample + i]); 33 } 34 } 35 writeIntLittle(int32_t n)36void WaveFileWriter::writeIntLittle(int32_t n) { 37 writeByte(n); 38 writeByte(n >> 8); 39 writeByte(n >> 16); 40 writeByte(n >> 24); 41 } 42 writeShortLittle(int16_t n)43void WaveFileWriter::writeShortLittle(int16_t n) { 44 writeByte(n); 45 writeByte(n >> 8); 46 } 47 writeFormatChunk()48void WaveFileWriter::writeFormatChunk() { 49 int32_t bytesPerSample = (mBitsPerSample + 7) / 8; 50 51 writeByte('f'); 52 writeByte('m'); 53 writeByte('t'); 54 writeByte(' '); 55 writeIntLittle(16); // chunk size 56 writeShortLittle(WAVE_FORMAT_PCM); 57 writeShortLittle((int16_t) mSamplesPerFrame); 58 writeIntLittle(mFrameRate); 59 // bytes/second 60 writeIntLittle(mFrameRate * mSamplesPerFrame * bytesPerSample); 61 // block align 62 writeShortLittle((int16_t) (mSamplesPerFrame * bytesPerSample)); 63 writeShortLittle((int16_t) mBitsPerSample); 64 } 65 getDataSizeInBytes()66int32_t WaveFileWriter::getDataSizeInBytes() { 67 if (mFrameCount <= 0) return INT32_MAX; 68 int64_t dataSize = ((int64_t)mFrameCount) * mSamplesPerFrame * mBitsPerSample / 8; 69 return (int32_t)std::min(dataSize, (int64_t)INT32_MAX); 70 } 71 writeDataChunkHeader()72void WaveFileWriter::writeDataChunkHeader() { 73 writeByte('d'); 74 writeByte('a'); 75 writeByte('t'); 76 writeByte('a'); 77 writeIntLittle(getDataSizeInBytes()); 78 } 79 writeHeader()80void WaveFileWriter::writeHeader() { 81 writeRiffHeader(); 82 writeFormatChunk(); 83 writeDataChunkHeader(); 84 mHeaderWritten = true; 85 } 86 87 // Write lower 8 bits. Upper bits ignored. writeByte(uint8_t b)88void WaveFileWriter::writeByte(uint8_t b) { 89 mOutputStream->write(b); 90 mBytesWritten += 1; 91 } 92 writePCM24(float value)93void WaveFileWriter::writePCM24(float value) { 94 // Offset before casting so that we can avoid using floor(). 95 // Also round by adding 0.5 so that very small signals go to zero. 96 float temp = (PCM24_MAX * value) + 0.5 - PCM24_MIN; 97 int32_t sample = ((int) temp) + PCM24_MIN; 98 // clip to 24-bit range 99 if (sample > PCM24_MAX) { 100 sample = PCM24_MAX; 101 } else if (sample < PCM24_MIN) { 102 sample = PCM24_MIN; 103 } 104 // encode as little-endian 105 writeByte(sample); // little end 106 writeByte(sample >> 8); // middle 107 writeByte(sample >> 16); // big end 108 } 109 writePCM16(float value)110void WaveFileWriter::writePCM16(float value) { 111 // Offset before casting so that we can avoid using floor(). 112 // Also round by adding 0.5 so that very small signals go to zero. 113 float temp = (INT16_MAX * value) + 0.5 - INT16_MIN; 114 int32_t sample = ((int) temp) + INT16_MIN; 115 if (sample > INT16_MAX) { 116 sample = INT16_MAX; 117 } else if (sample < INT16_MIN) { 118 sample = INT16_MIN; 119 } 120 writeByte(sample); // little end 121 writeByte(sample >> 8); // big end 122 } 123 writeRiffHeader()124void WaveFileWriter::writeRiffHeader() { 125 writeByte('R'); 126 writeByte('I'); 127 writeByte('F'); 128 writeByte('F'); 129 // Maximum size is not strictly correct but is commonly used 130 // when we do not know the final size. 131 const int kExtraHeaderBytes = 36; 132 int32_t dataSize = getDataSizeInBytes(); 133 writeIntLittle((dataSize > (INT32_MAX - kExtraHeaderBytes)) 134 ? INT32_MAX 135 : dataSize + kExtraHeaderBytes); 136 writeByte('W'); 137 writeByte('A'); 138 writeByte('V'); 139 writeByte('E'); 140 } 141