• 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 #include "WaveFileWriter.h"
18 
write(float value)19 void 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)30 void 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)36 void 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)43 void WaveFileWriter::writeShortLittle(int16_t n) {
44     writeByte(n);
45     writeByte(n >> 8);
46 }
47 
writeFormatChunk()48 void 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()66 void 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()76 void 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)84 void WaveFileWriter::writeByte(uint8_t b) {
85     mOutputStream->write(b);
86     bytesWritten += 1;
87 }
88 
writePCM24(float value)89 void 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)106 void 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()120 void 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