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>xcode15
parent
e330c64f43
commit
c612994cb2
|
@ -20,6 +20,7 @@
|
|||
double srate;
|
||||
uint32_t channelCount;
|
||||
uint32_t channelConfig;
|
||||
float tempBuffer[4096 * 2];
|
||||
}
|
||||
|
||||
- (id)initWithSampleRate:(double)srate;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
double latency;
|
||||
float *visAudio;
|
||||
int visAudioCursor, visAudioSize;
|
||||
float *visAudioTemp;
|
||||
}
|
||||
|
||||
+ (VisualizationController *)sharedController;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -24,5 +24,7 @@
|
|||
long framesFade;
|
||||
long framesRead;
|
||||
long framesInBuffer;
|
||||
|
||||
float sampleBuffer[1024 * 2];
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
long length;
|
||||
long remain;
|
||||
|
||||
float *buffer;
|
||||
}
|
||||
|
||||
- (void)setSource:(id<CogSource>)s;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue