Skip to content

Commit 1b44603

Browse files
committed
Fix badly architectured audio file reads
Removes most of the reallocations that happen because the file size is not known in advance.
1 parent 8dd80ed commit 1b44603

File tree

7 files changed

+75
-38
lines changed

7 files changed

+75
-38
lines changed

src/engine/audio/ALObjects.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ namespace AL {
135135
ALuint format = Format(audioData.byteDepth, audioData.numberOfChannels);
136136

137137
CHECK_AL_ERROR();
138-
alBufferData(alHandle, format, audioData.rawSamples.get(), audioData.size,
138+
alBufferData(alHandle, format, audioData.rawSamples.data(), audioData.rawSamples.size(),
139139
audioData.sampleRate);
140140

141141
return ClearALError();

src/engine/audio/Audio.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,10 @@ namespace Audio {
383383

384384
streams[streamNum]->SetGain(volume);
385385

386-
AudioData audioData(rate, width, channels, (width * numSamples * channels),
387-
reinterpret_cast<const char*>(data));
386+
AudioData audioData { rate, width, channels };
387+
audioData.rawSamples.resize( width * numSamples * channels );
388+
memcpy( audioData.rawSamples.data(), data, width * numSamples * channels * sizeof( char ) );
389+
388390
AL::Buffer buffer;
389391

390392
int feedError = buffer.Feed(audioData);
@@ -506,9 +508,10 @@ namespace Audio {
506508
int numSamples = AvailableCaptureSamples();
507509

508510
if (numSamples > 0) {
509-
uint16_t* buffer = new uint16_t[numSamples];
511+
uint16_t* buffer = ( uint16_t* ) Hunk_AllocateTempMemory( numSamples * sizeof( uint16_t ) );
510512
GetCapturedData(numSamples, buffer);
511513
StreamData(N_STREAMS - 1, buffer, numSamples, 16000, 2, 1, 1.0, -1);
514+
Hunk_FreeTempMemory( buffer );
512515
}
513516
}
514517

src/engine/audio/AudioData.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131
#ifndef AUDIO_DATA_H
3232
#define AUDIO_DATA_H
3333
#include <memory>
34+
#include <vector>
3435

3536
namespace Audio {
3637

@@ -39,23 +40,18 @@ struct AudioData {
3940
: sampleRate{0}
4041
, byteDepth{0}
4142
, numberOfChannels{0}
42-
, size{0}
43-
, rawSamples{nullptr}
4443
{}
4544

46-
AudioData(int sampleRate, int byteDepth, int numberOfChannels, int size, const char* rawSamples)
45+
AudioData(int sampleRate, int byteDepth, int numberOfChannels )
4746
: sampleRate{sampleRate}
4847
, byteDepth{byteDepth}
4948
, numberOfChannels{numberOfChannels}
50-
, size{size}
51-
, rawSamples{rawSamples}
5249
{}
5350

5451
AudioData(AudioData&& that)
5552
: sampleRate{that.sampleRate}
5653
, byteDepth{that.byteDepth}
5754
, numberOfChannels{that.numberOfChannels}
58-
, size{that.size}
5955
, rawSamples{std::move(that.rawSamples)}
6056
{}
6157

@@ -64,8 +60,7 @@ struct AudioData {
6460
const int sampleRate;
6561
const int byteDepth;
6662
const int numberOfChannels;
67-
const int size;
68-
std::unique_ptr<const char[]> rawSamples;
63+
std::vector<char> rawSamples;
6964
};
7065
} // namespace Audio
7166
#endif

src/engine/audio/OggCodec.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,42 @@ AudioData LoadOggCodec(std::string filename)
151151
int sampleRate = oggInfo->rate;
152152
int numberOfChannels = oggInfo->channels;
153153

154-
char buffer[4096];
154+
/* The largest ogg file we have so far is res-soundtrack/sound/ui/heartbeat.ogg
155+
It uncompress to ~47mb. Use 64mb here just in case */
156+
static constexpr uint32_t MAX_USED_FILE_SIZE = 64 * 1024 * 1024;
157+
static constexpr uint32_t MAX_READ_SIZE = 1 * 1024 * 1024;
158+
159+
char* buffer = ( char* ) Hunk_AllocateTempMemory( MAX_USED_FILE_SIZE );
160+
uint32_t bufferPointer = 0;
161+
uint32_t rawSamplesPointer = 0;
162+
155163
int bytesRead = 0;
156164
int bitStream = 0;
157165

158-
std::vector<char> samples;
166+
AudioData out { sampleRate, sampleWidth, numberOfChannels };
167+
168+
while ((bytesRead = ov_read(vorbisFile.get(), buffer + bufferPointer, MAX_READ_SIZE, 0, sampleWidth, 1, &bitStream)) > 0) {
169+
bufferPointer += bytesRead;
170+
171+
if ( MAX_USED_FILE_SIZE - bufferPointer < MAX_READ_SIZE ) {
172+
out.rawSamples.resize( out.rawSamples.size() + bufferPointer );
173+
std::copy_n( buffer, bufferPointer, out.rawSamples.data() + rawSamplesPointer );
159174

160-
while ((bytesRead = ov_read(vorbisFile.get(), buffer, 4096, 0, sampleWidth, 1, &bitStream)) > 0) {
161-
std::copy_n(buffer, bytesRead, std::back_inserter(samples));
175+
rawSamplesPointer += bufferPointer;
176+
bufferPointer = 0;
177+
}
162178
}
179+
180+
if ( bufferPointer ) {
181+
out.rawSamples.resize( out.rawSamples.size() + bufferPointer );
182+
std::copy_n( buffer, bufferPointer, out.rawSamples.data() + rawSamplesPointer );
183+
}
184+
185+
Hunk_FreeTempMemory( buffer );
186+
163187
ov_clear(vorbisFile.get());
164188

165-
char* rawSamples = new char[samples.size()];
166-
std::copy_n(samples.data(), samples.size(), rawSamples);
167-
return AudioData(sampleRate, sampleWidth, numberOfChannels, samples.size(), rawSamples);
189+
return out;
168190
}
169191

170192
} //namespace Audio

src/engine/audio/OpusCodec.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,43 @@ AudioData LoadOpusCodec(std::string filename)
145145
int sampleRate = 48000;
146146
int numberOfChannels = opusInfo->channel_count;
147147

148-
// The buffer is big enough to hold 120ms worth of samples per channel
149-
opus_int16* buffer = new opus_int16[numberOfChannels * 5760];
148+
/* The largest opus file we have so far is sound/thunder/weather.opus
149+
It uncompress to ~13mb. Use 64mb here just in case */
150+
static constexpr uint32_t MAX_USED_FILE_SIZE = 64 * 1024 * 1024;
151+
static constexpr uint32_t MAX_READ_SIZE = 1 * 1024 * 1024;
152+
153+
char* buffer = ( char* ) Hunk_AllocateTempMemory( MAX_USED_FILE_SIZE );
154+
uint32_t bufferPointer = 0;
155+
uint32_t rawSamplesPointer = 0;
156+
150157
int samplesPerChannelRead = 0;
151158

152-
std::vector<opus_int16> samples;
159+
AudioData out { sampleRate, sampleWidth, numberOfChannels };
160+
161+
while ( ( samplesPerChannelRead =
162+
op_read( opusFile, ( opus_int16* ) ( buffer + bufferPointer ), MAX_READ_SIZE, nullptr )
163+
) > 0 ) {
164+
bufferPointer += samplesPerChannelRead * numberOfChannels * sizeof( opus_int16 );
165+
166+
if ( MAX_USED_FILE_SIZE - bufferPointer < MAX_READ_SIZE ) {
167+
out.rawSamples.resize( out.rawSamples.size() + bufferPointer );
168+
std::copy_n( buffer, bufferPointer, out.rawSamples.data() + rawSamplesPointer );
153169

154-
while ((samplesPerChannelRead =
155-
op_read(opusFile, buffer, sampleWidth * numberOfChannels * 5760, nullptr)) > 0) {
156-
std::copy_n(buffer, samplesPerChannelRead * numberOfChannels, std::back_inserter(samples));
170+
rawSamplesPointer += bufferPointer;
171+
bufferPointer = 0;
172+
}
157173
}
158174

159-
delete[] buffer;
160-
op_free(opusFile);
175+
if ( bufferPointer ) {
176+
out.rawSamples.resize( out.rawSamples.size() + bufferPointer );
177+
std::copy_n( buffer, bufferPointer, out.rawSamples.data() + rawSamplesPointer );
178+
}
161179

162-
char* rawSamples = new char[sampleWidth * samples.size()];
163-
std::copy_n(reinterpret_cast<char*>(samples.data()), sampleWidth * samples.size(), rawSamples);
180+
Hunk_FreeTempMemory( buffer );
181+
182+
op_free(opusFile);
164183

165-
return AudioData(sampleRate, sampleWidth, numberOfChannels, samples.size() * sampleWidth,
166-
rawSamples);
184+
return out;
167185
}
168186

169187
} //namespace Audio

src/engine/audio/Sample.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ namespace Audio {
4646

4747
bool Sample::Load() {
4848
audioLogs.Debug("Loading Sample '%s'", GetName());
49-
auto audioData = LoadSoundCodec(GetName());
49+
AudioData audioData = LoadSoundCodec(GetName());
5050

51-
if (audioData.size == 0) {
51+
if ( !audioData.rawSamples.size() ) {
5252
audioLogs.Debug("Couldn't load sound %s, it's empty!", GetName());
5353
return false;
5454
}

src/engine/audio/WavCodec.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,15 @@ AudioData LoadWavCodec(std::string filename)
108108

109109
int size = PackChars(audioFile, dataOffset + 4, 4);
110110

111-
if (size <= 0 || sampleRate <=0 ){
111+
if (size <= 0 || sampleRate <= 0 ) {
112112
audioLogs.Warn("Error in reading %s.", filename);
113113
return AudioData();
114114
}
115115

116-
char* data = new char[size];
116+
AudioData out { sampleRate, byteDepth, numChannels };
117+
out.rawSamples.assign( audioFile.data() + dataOffset + 8, audioFile.data() + size );
117118

118-
std::copy_n(audioFile.data() + dataOffset + 8, size, data);
119-
120-
return AudioData(sampleRate, byteDepth, numChannels, size, data);
119+
return out;
121120
}
122121

123122
} // namespace Audio

0 commit comments

Comments
 (0)