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 (!headerWritten) { 21 writeHeader(); 22 } 23 if (bitsPerSample == 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 = (bitsPerSample + 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) bitsPerSample); 64 } 65 writeDataChunkHeader()66void WaveFileWriter::writeDataChunkHeader() { 67 writeByte('d'); 68 writeByte('a'); 69 writeByte('t'); 70 writeByte('a'); 71 // Maximum size is not strictly correct but is commonly used 72 // when we do not know the final size. 73 writeIntLittle(INT32_MAX); 74 } 75 writeHeader()76void WaveFileWriter::writeHeader() { 77 writeRiffHeader(); 78 writeFormatChunk(); 79 writeDataChunkHeader(); 80 headerWritten = true; 81 } 82 83 // Write lower 8 bits. Upper bits ignored. writeByte(uint8_t b)84void WaveFileWriter::writeByte(uint8_t b) { 85 mOutputStream->write(b); 86 bytesWritten += 1; 87 } 88 writePCM24(float value)89void WaveFileWriter::writePCM24(float value) { 90 // Offset before casting so that we can avoid using floor(). 91 // Also round by adding 0.5 so that very small signals go to zero. 92 float temp = (PCM24_MAX * value) + 0.5 - PCM24_MIN; 93 int32_t sample = ((int) temp) + PCM24_MIN; 94 // clip to 24-bit range 95 if (sample > PCM24_MAX) { 96 sample = PCM24_MAX; 97 } else if (sample < PCM24_MIN) { 98 sample = PCM24_MIN; 99 } 100 // encode as little-endian 101 writeByte(sample); // little end 102 writeByte(sample >> 8); // middle 103 writeByte(sample >> 16); // big end 104 } 105 writePCM16(float value)106void WaveFileWriter::writePCM16(float value) { 107 // Offset before casting so that we can avoid using floor(). 108 // Also round by adding 0.5 so that very small signals go to zero. 109 float temp = (INT16_MAX * value) + 0.5 - INT16_MIN; 110 int32_t sample = ((int) temp) + INT16_MIN; 111 if (sample > INT16_MAX) { 112 sample = INT16_MAX; 113 } else if (sample < INT16_MIN) { 114 sample = INT16_MIN; 115 } 116 writeByte(sample); // little end 117 writeByte(sample >> 8); // big end 118 } 119 writeRiffHeader()120void WaveFileWriter::writeRiffHeader() { 121 writeByte('R'); 122 writeByte('I'); 123 writeByte('F'); 124 writeByte('F'); 125 // Maximum size is not strictly correct but is commonly used 126 // when we do not know the final size. 127 writeIntLittle(INT32_MAX); 128 writeByte('W'); 129 writeByte('A'); 130 writeByte('V'); 131 writeByte('E'); 132 } 133