Move most large stack using buffers to the heap

This should solve most potential future stack overflows.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
main
Christopher Snowhill 2022-07-24 18:31:08 -07:00
parent eec8bf9f1c
commit ddbc38c7fe
16 changed files with 106 additions and 75 deletions

View File

@ -20,6 +20,7 @@
double srate;
uint32_t channelCount;
uint32_t channelConfig;
float tempBuffer[4096 * 2];
}
- (id)initWithSampleRate:(double)srate;

View File

@ -129,7 +129,6 @@ struct freesurround_params {
freesurround_params *_params = (freesurround_params *)params;
freesurround_decoder *_decoder = (freesurround_decoder *)decoder;
float tempInput[4096 * 2];
uint32_t zeroCount = 0;
if(count > 4096) {
@ -138,9 +137,9 @@ struct freesurround_params {
}
if(count < 4096) {
cblas_scopy(count * 2, samplesIn, 1, &tempInput[0], 1);
vDSP_vclr(&tempInput[count * 2], 1, (4096 - count) * 2);
samplesIn = &tempInput[0];
cblas_scopy(count * 2, samplesIn, 1, &tempBuffer[0], 1);
vDSP_vclr(&tempBuffer[count * 2], 1, (4096 - count) * 2);
samplesIn = &tempBuffer[0];
}
float *src = _decoder->decode(samplesIn);

View File

@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
double latency;
float *visAudio;
int visAudioCursor, visAudioSize;
float *visAudioTemp;
}
+ (VisualizationController *)sharedController;

View File

@ -28,6 +28,10 @@ static VisualizationController *_sharedController = nil;
if(self) {
visAudio = NULL;
latency = 0;
visAudioTemp = (float *) calloc(sizeof(float), 4096);
if(!visAudioTemp) {
return nil;
}
}
return self;
}
@ -89,8 +93,7 @@ static VisualizationController *_sharedController = nil;
return;
}
float tempPCM[4096];
if(!outPCM) outPCM = &tempPCM[0];
if(!outPCM) outPCM = &visAudioTemp[0];
@synchronized(self) {
if(!sampleRate) {

View File

@ -30,17 +30,19 @@ Unpack::Unpack(ComprDataIO *DataIO)
void Unpack::init_tables()
{
ComprDataIO IOTemp;
Unpack Temp(&IOTemp);
ComprDataIO *IOTemp = new ComprDataIO;
Unpack *Temp = new Unpack(IOTemp);
// Perform initialization, which should be done only once for all files.
// It prevents crash if first DoUnpack call is later made with wrong
// (true) 'Solid' value.
Temp.UnpInitData(false);
Temp->UnpInitData(false);
#ifndef SFX_MODULE
// RAR 1.5 decompression initialization
Temp.UnpInitData15(false);
Temp.InitHuff();
Temp->UnpInitData15(false);
Temp->InitHuff();
#endif
delete Temp;
delete IOTemp;
}

View File

@ -21,6 +21,8 @@ extern gme_err_t readCallback(void* data, void* out, int count);
long length;
long fade;
NSString* codec;
int16_t sampleBuffer[1024 * 2];
}
- (void)setSource:(id<CogSource>)s;

View File

@ -176,8 +176,7 @@ gme_err_t readCallback(void *data, void *out, int count) {
- (AudioChunk *)readAudio {
int frames = 1024;
int16_t buffer[frames * 2];
void *buf = (void *)buffer;
void *buf = (void *)sampleBuffer;
id audioChunkClass = NSClassFromString(@"AudioChunk");
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
@ -199,7 +198,7 @@ gme_err_t readCallback(void *data, void *out, int count) {
//(From gme.txt) If track length, then use it. If loop length, play for intro + loop * 2. Otherwise, default to 2.5 minutes
// GME will always generate samples. There's no real EOS.
[chunk assignSamples:buffer frameCount:numSamples];
[chunk assignSamples:sampleBuffer frameCount:numSamples];
return chunk;
}

View File

@ -24,5 +24,7 @@
long framesFade;
long framesRead;
long framesInBuffer;
float sampleBuffer[1024 * 2];
}
@end

View File

@ -10,6 +10,8 @@
#import "PlaylistController.h"
#import <Accelerate/Accelerate.h>
static void oneTimeInit(void) {
static BOOL initialized = NO;
if(!initialized) {
@ -109,8 +111,7 @@ static void oneTimeInit(void) {
- (AudioChunk *)readAudio {
int frames = 1024;
float buffer[frames * 2];
void *buf = (void *)buffer;
void *buf = (void *)sampleBuffer;
BOOL repeatone = IsRepeatOneSet();
@ -124,11 +125,9 @@ static void oneTimeInit(void) {
int framesToCopy = frames - total;
if(framesToCopy > framesInBuffer)
framesToCopy = (int)framesInBuffer;
for(int i = 0; i < framesToCopy; ++i) {
outbuffer[0] = buffer[i * 2 + 0] * (1.0f / 16777216.0f);
outbuffer[1] = buffer[i * 2 + 1] * (1.0f / 16777216.0f);
outbuffer += 2;
}
vDSP_vflt32(&buffer[0], 1, &outbuffer[0], 1, framesToCopy * 2);
float scale = 16777216.0f;
vDSP_vsdiv(&outbuffer[0], 1, &scale, &outbuffer[0], 1, framesToCopy * 2);
framesInBuffer -= framesToCopy;
total += framesToCopy;
if(framesInBuffer) {
@ -163,7 +162,7 @@ static void oneTimeInit(void) {
id audioChunkClass = NSClassFromString(@"AudioChunk");
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
[chunk assignSamples:buffer frameCount:total];
[chunk assignSamples:sampleBuffer frameCount:total];
return chunk;
}

View File

@ -74,29 +74,36 @@
}
- (BOOL)scanFile {
struct mad_stream stream;
struct mad_frame frame;
struct mad_stream *stream;
struct mad_frame *frame;
stream = (struct mad_stream *) calloc(sizeof(struct mad_stream), 1);
frame = (struct mad_frame *) calloc(sizeof(struct mad_frame), 1);
if(!stream || !frame) {
ALog(@"Out of memory!");
return NO;
}
long framesDecoded = 0;
int samplesPerMPEGFrame = 0;
int id3_length = 0;
mad_stream_init(&stream);
mad_frame_init(&frame);
mad_stream_init(stream);
mad_frame_init(frame);
[_source seek:0 whence:SEEK_END];
_fileSize = [_source tell];
[_source seek:0 whence:SEEK_SET];
for(;;) {
[self bufferRefill:&stream];
[self bufferRefill:stream];
if(mad_frame_decode(&frame, &stream) == -1) {
if(MAD_RECOVERABLE(stream.error)) {
if(mad_frame_decode(frame, stream) == -1) {
if(MAD_RECOVERABLE(stream->error)) {
// Prevent ID3 tags from reporting recoverable frame errors
const uint8_t *buffer = stream.this_frame;
unsigned long buflen = stream.bufend - stream.this_frame;
const uint8_t *buffer = stream->this_frame;
unsigned long buflen = stream->bufend - stream->this_frame;
if(10 <= buflen && 0x49 == buffer[0] && 0x44 == buffer[1] && 0x33 == buffer[2]) {
id3_length = (((buffer[6] & 0x7F) << (3 * 7)) | ((buffer[7] & 0x7F) << (2 * 7)) |
@ -108,7 +115,7 @@
id3_length += 10;
void *tagBuffer = malloc(id3_length);
if(!tagBuffer) return NO;
if(!tagBuffer) goto error;
memcpy(tagBuffer, &buffer[0], MIN(buflen, id3_length));
@ -116,18 +123,18 @@
long tagRead = MIN(buflen, id3_length);
while(bufleft > 0) {
stream.error = MAD_ERROR_BUFLEN;
stream.next_frame = NULL;
[self bufferRefill:&stream];
buffer = stream.this_frame;
buflen = stream.bufend - stream.this_frame;
stream->error = MAD_ERROR_BUFLEN;
stream->next_frame = NULL;
[self bufferRefill:stream];
buffer = stream->this_frame;
buflen = stream->bufend - stream->this_frame;
memcpy(tagBuffer + tagRead, buffer, MIN(buflen, bufleft));
tagRead += MIN(buflen, bufleft);
bufleft -= buflen;
}
if(bufleft < 0) {
mad_stream_skip(&stream, buflen + bufleft);
mad_stream_skip(stream, buflen + bufleft);
}
struct id3_tag *tag = id3_tag_parse(tagBuffer, id3_length);
@ -180,14 +187,14 @@
}
free(tagBuffer);
} else if(stream.error == MAD_ERROR_BADDATAPTR) {
} else if(stream->error == MAD_ERROR_BADDATAPTR) {
goto framedecoded;
}
continue;
} else if(stream.error == MAD_ERROR_BUFLEN && inputEOF) {
} else if(stream->error == MAD_ERROR_BUFLEN && inputEOF) {
break;
} else if(stream.error == MAD_ERROR_BUFLEN) {
} else if(stream->error == MAD_ERROR_BUFLEN) {
continue;
} else {
// DLog(@"Unrecoverable error: %s", mad_stream_errorstr(&stream));
@ -198,11 +205,11 @@
framesDecoded++;
if(framesDecoded == 1) {
sampleRate = frame.header.samplerate;
channels = MAD_NCHANNELS(&frame.header);
sampleRate = frame->header.samplerate;
channels = MAD_NCHANNELS(&frame->header);
if(MAD_FLAG_LSF_EXT & frame.header.flags || MAD_FLAG_MPEG_2_5_EXT & frame.header.flags) {
switch(frame.header.layer) {
if(MAD_FLAG_LSF_EXT & frame->header.flags || MAD_FLAG_MPEG_2_5_EXT & frame->header.flags) {
switch(frame->header.layer) {
case MAD_LAYER_I:
samplesPerMPEGFrame = 384;
layer = 1;
@ -217,7 +224,7 @@
break;
}
} else {
switch(frame.header.layer) {
switch(frame->header.layer) {
case MAD_LAYER_I:
samplesPerMPEGFrame = 384;
layer = 1;
@ -235,16 +242,16 @@
if(layer != 3) continue;
const size_t ancillaryBitsRemaining = (stream.next_frame - stream.this_frame) * 8;
const size_t ancillaryBitsRemaining = (stream->next_frame - stream->this_frame) * 8;
static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
const int64_t xing_offset = xing_offtbl[!!(MAD_FLAG_LSF_EXT & frame.header.flags || MAD_FLAG_MPEG_2_5_EXT & frame.header.flags)][channels == 1] + 4; // Plus MPEG header
const int64_t xing_offset = xing_offtbl[!!(MAD_FLAG_LSF_EXT & frame->header.flags || MAD_FLAG_MPEG_2_5_EXT & frame->header.flags)][channels == 1] + 4; // Plus MPEG header
size_t ancBitsRemainingXing = ancillaryBitsRemaining - xing_offset * 8;
if(ancBitsRemainingXing >= 32) {
const uint8_t *ptr = stream.this_frame + xing_offset;
const uint8_t *ptr = stream->this_frame + xing_offset;
struct mad_bitptr bitptr;
mad_bit_init(&bitptr, ptr);
@ -374,7 +381,7 @@
size_t ancBitsRemainingVBRI = ancillaryBitsRemaining - vbri_offset * 8;
if(ancBitsRemainingVBRI >= 32) {
const uint8_t *ptr = stream.this_frame + vbri_offset;
const uint8_t *ptr = stream->this_frame + vbri_offset;
struct mad_bitptr bitptr;
mad_bit_init(&bitptr, ptr);
@ -407,22 +414,25 @@
}
// Don't commit division by zero on bad files
if(stream.next_frame == stream.this_frame) {
return NO;
if(stream->next_frame == stream->this_frame) {
goto error;
}
if(!_foundiTunSMPB && !_foundXingHeader && !_foundVBRIHeader) {
// Now do CBR estimation instead of full file scanning
size_t frameCount = (_fileSize - id3_length) / (stream.next_frame - stream.this_frame);
mad_timer_t duration = frame.header.duration;
size_t frameCount = (_fileSize - id3_length) / (stream->next_frame - stream->this_frame);
mad_timer_t duration = frame->header.duration;
mad_timer_multiply(&duration, frameCount);
totalFrames = mad_timer_count(duration, sampleRate);
}
bitrate = ((double)((_fileSize - id3_length) * 8) / 1000.0) * (sampleRate / (double)totalFrames);
mad_frame_finish(&frame);
mad_stream_finish(&stream);
mad_frame_finish(frame);
mad_stream_finish(stream);
free(frame);
free(stream);
[_source seek:0 whence:SEEK_SET];
inputEOF = NO;
@ -430,6 +440,17 @@
DLog(@"Mad properties: %@", [self properties]);
return YES;
error:
if(frame) {
mad_frame_finish(frame);
free(frame);
}
if(stream) {
mad_stream_finish(stream);
free(stream);
}
return NO;
}
- (BOOL)open:(id<CogSource>)source {

View File

@ -20,6 +20,9 @@
char buffer[MPC_FRAME_LENGTH * 4];
int bufferFrames;
MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH];
float floatBuffer[1024 * 2];
int bitrate;
float frequency;

View File

@ -110,11 +110,8 @@ mpc_bool_t CanSeekProc(mpc_reader *p_reader) {
}
- (AudioChunk *)readAudio {
MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH];
int frames = 1024;
float buffer[frames * 2];
void *buf = (void *)buffer;
void *buf = (void *)floatBuffer;
int framesRead = 0;
int bytesPerFrame = sizeof(float) * 2; // bitsPerSample == 32, channels == 2
@ -156,7 +153,7 @@ mpc_bool_t CanSeekProc(mpc_reader *p_reader) {
id audioChunkClass = NSClassFromString(@"AudioChunk");
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
[chunk assignSamples:buffer frameCount:framesRead];
[chunk assignSamples:floatBuffer frameCount:framesRead];
return chunk;
}

View File

@ -15,6 +15,8 @@
long length;
long remain;
float *buffer;
}
- (void)setSource:(id<CogSource>)s;

View File

@ -27,6 +27,12 @@ enum { channels = 2 };
length = seconds * sample_rate;
remain = length;
buffer = (float *) calloc(sizeof(float), 1024 * channels);
if(!buffer) {
ALog(@"Out of memory!");
return NO;
}
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
@ -52,23 +58,17 @@ enum { channels = 2 };
- (AudioChunk *)readAudio {
int frames = 1024;
float buffer[frames * channels];
void *buf = (void *)buffer;
int total = frames;
if(!IsRepeatOneSet()) {
if(total > remain)
total = (int)remain;
if(frames > remain)
frames = (int)remain;
remain -= total;
remain -= frames;
}
memset(buf, 0, sizeof(float) * total * channels);
id audioChunkClass = NSClassFromString(@"AudioChunk");
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
[chunk assignSamples:buffer frameCount:total];
[chunk assignSamples:buffer frameCount:frames];
return chunk;
}

View File

@ -39,6 +39,8 @@ extern NSString *CogPlaybackDidStopNotficiation;
NSColor *borderColor;
ddb_analyzer_t _analyzer;
ddb_analyzer_draw_data_t _draw_data;
float visAudio[4096], visFFT[2048];
}
@end
@ -368,8 +370,6 @@ extern NSString *CogPlaybackDidStopNotficiation;
_analyzer.view_width = self.bounds.size.width;
}
float visAudio[4096], visFFT[2048];
[self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:0];
ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048);

View File

@ -42,6 +42,8 @@ extern NSString *CogPlaybackDidStopNotficiation;
SCNVector3 cameraEulerAngles2d;
SCNVector3 cameraPosition3d;
SCNVector3 cameraEulerAngles3d;
float visAudio[4096], visFFT[2048];
}
@end
@ -274,8 +276,6 @@ extern NSString *CogPlaybackDidStopNotficiation;
return;
}
float visAudio[4096], visFFT[2048];
[self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:0];
ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048);