@@ -40,7 +40,9 @@ void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
4040 DLog (@" - - - - - - - - - - - - - - - - - - - -\n " );
4141}
4242
43- @implementation ConverterNode
43+ @implementation ConverterNode {
44+ NSRecursiveLock *mutex;
45+ }
4446
4547static void *kConverterNodeContext = &kConverterNodeContext ;
4648
@@ -58,7 +60,6 @@ - (id)initWithController:(id)c previous:(id)p {
5860 floatBufferSize = 0 ;
5961
6062 stopping = NO ;
61- convertEntered = NO ;
6263 paused = NO ;
6364
6465 resetProcessed = NO ;
@@ -68,6 +69,8 @@ - (id)initWithController:(id)c previous:(id)p {
6869 extrapolateBuffer = NULL ;
6970 extrapolateBufferSize = 0 ;
7071
72+ mutex = [[NSRecursiveLock alloc ] init ];
73+
7174#ifdef LOG_CHAINS
7275 [self initLogFiles ];
7376#endif
@@ -137,8 +140,10 @@ - (void)process {
137140 chunk = nil ;
138141 }
139142 if (streamFormatChanged) {
143+ [mutex lock ];
140144 [self cleanUp ];
141145 [self setupWithInputFormat: newInputFormat withInputConfig: newInputChannelConfig outputFormat: self ->outputFormat isLossless: rememberedLossless];
146+ [mutex unlock ];
142147 }
143148 }
144149 }
@@ -151,18 +156,18 @@ - (AudioChunk *)convert {
151156 if (stopping)
152157 return 0 ;
153158
154- convertEntered = YES ;
159+ [mutex lock ] ;
155160
156161 if (stopping || [self shouldContinue ] == NO ) {
157- convertEntered = NO ;
162+ [mutex unlock ] ;
158163 return nil ;
159164 }
160165
161166 if (inpOffset == inpSize) {
162167 streamTimestamp = 0.0 ;
163168 streamTimeRatio = 1.0 ;
164169 if (![self peekTimestamp: &streamTimestamp timeRatio: &streamTimeRatio]) {
165- convertEntered = NO ;
170+ [mutex unlock ] ;
166171 return nil ;
167172 }
168173 }
@@ -219,7 +224,7 @@ - (AudioChunk *)convert {
219224 }
220225
221226 if (!bytesReadFromInput) {
222- convertEntered = NO ;
227+ [mutex unlock ] ;
223228 return nil ;
224229 }
225230
@@ -296,7 +301,7 @@ - (AudioChunk *)convert {
296301 }
297302
298303 if (stopping) {
299- convertEntered = NO ;
304+ [mutex unlock ] ;
300305 return nil ;
301306 }
302307
@@ -362,11 +367,11 @@ - (AudioChunk *)convert {
362367 resetProcessed = NO ;
363368 }
364369 streamTimestamp += [chunk durationRatioed ];
365- convertEntered = NO ;
370+ [mutex unlock ] ;
366371 return chunk;
367372 }
368373
369- convertEntered = NO ;
374+ [mutex unlock ] ;
370375 return nil ;
371376}
372377
@@ -432,6 +437,8 @@ - (void)refreshVolumeScaling {
432437
433438- (BOOL )setupWithInputFormat : (AudioStreamBasicDescription)inf withInputConfig : (uint32_t )inputConfig outputFormat : (AudioStreamBasicDescription)outf isLossless : (BOOL )lossless {
434439 // Make the converter
440+ [mutex lock ];
441+
435442 inputFormat = inf;
436443 outputFormat = outf;
437444
@@ -441,8 +448,10 @@ - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(u
441448
442449 // These are the only sample formats we support translating
443450 BOOL isFloat = !!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat );
444- if ((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32 )) || (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64 )))
451+ if ((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32 )) || (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64 ))) {
452+ [mutex unlock ];
445453 return NO ;
454+ }
446455
447456 floatFormat = inputFormat;
448457 floatFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked ;
@@ -475,8 +484,10 @@ - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(u
475484 soxr_error_t error;
476485
477486 soxr = soxr_create (floatFormat.mSampleRate , outputFormat.mSampleRate , floatFormat.mChannelsPerFrame , &error, &io_spec, &q_spec, &runtime_spec);
478- if (error)
487+ if (error) {
488+ [mutex unlock ];
479489 return NO ;
490+ }
480491
481492 PRIME_LEN_ = MAX (floatFormat.mSampleRate / 20 , 1024u );
482493 PRIME_LEN_ = MIN (PRIME_LEN_, 16384u );
@@ -501,10 +512,11 @@ - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(u
501512
502513 // Move this here so process call isn't running the resampler until it's allocated
503514 stopping = NO ;
504- convertEntered = NO ;
505515 streamFormatChanged = NO ;
506516 paused = NO ;
507517
518+ [mutex unlock ];
519+
508520 return YES ;
509521}
510522
@@ -526,11 +538,10 @@ - (void)setOutputFormat:(AudioStreamBasicDescription)format {
526538- (void )inputFormatDidChange : (AudioStreamBasicDescription)format inputConfig : (uint32_t )inputConfig {
527539 DLog (@" FORMAT CHANGED" );
528540 paused = YES ;
529- while (convertEntered) {
530- usleep (500 );
531- }
541+ [mutex lock ];
532542 [self cleanUp ];
533543 [self setupWithInputFormat: format withInputConfig: inputConfig outputFormat: self ->outputFormat isLossless: rememberedLossless];
544+ [mutex unlock ];
534545}
535546
536547- (void )setRGInfo : (NSDictionary *)rgi {
@@ -541,9 +552,7 @@ - (void)setRGInfo:(NSDictionary *)rgi {
541552
542553- (void )cleanUp {
543554 stopping = YES ;
544- while (convertEntered) {
545- usleep (500 );
546- }
555+ [mutex lock ];
547556 if (soxr) {
548557 soxr_delete (soxr);
549558 soxr = NULL ;
@@ -565,6 +574,7 @@ - (void)cleanUp {
565574 }
566575 inpOffset = 0 ;
567576 inpSize = 0 ;
577+ [mutex unlock ];
568578}
569579
570580- (double )secondsBuffered {
0 commit comments