expo-juce 0.2.18 → 0.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/JuceToneGenerator.mm +4 -90
- package/package.json +1 -1
package/ios/JuceToneGenerator.mm
CHANGED
|
@@ -292,96 +292,10 @@ private:
|
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
- (void)initialize {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
NSLog(@"[ExpoJuce] Initializing audio engine...");
|
|
301
|
-
|
|
302
|
-
@try {
|
|
303
|
-
NSError *error = nil;
|
|
304
|
-
|
|
305
|
-
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
306
|
-
[audioSession setCategory:AVAudioSessionCategoryPlayback
|
|
307
|
-
withOptions:AVAudioSessionCategoryOptionMixWithOthers
|
|
308
|
-
error:&error];
|
|
309
|
-
if (error) {
|
|
310
|
-
NSLog(@"[ExpoJuce] Error setting audio session category: %@", error);
|
|
311
|
-
error = nil;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
[audioSession setActive:YES error:&error];
|
|
315
|
-
if (error) {
|
|
316
|
-
NSLog(@"[ExpoJuce] Error activating audio session: %@", error);
|
|
317
|
-
error = nil;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
self.audioEngine = [[AVAudioEngine alloc] init];
|
|
321
|
-
|
|
322
|
-
// Use the hardware sample rate to avoid format mismatches
|
|
323
|
-
double sampleRate = audioSession.sampleRate > 0 ? audioSession.sampleRate : 44100.0;
|
|
324
|
-
AVAudioFormat *format = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:sampleRate channels:2];
|
|
325
|
-
NSLog(@"[ExpoJuce] Using sample rate: %.0f", sampleRate);
|
|
326
|
-
|
|
327
|
-
SynthEngine *eng = self.engine;
|
|
328
|
-
TransportEngine *trans = self.transport;
|
|
329
|
-
|
|
330
|
-
struct BeatState {
|
|
331
|
-
std::atomic<bool> crossed{false};
|
|
332
|
-
std::atomic<double> beat{0.0};
|
|
333
|
-
std::atomic<double> bpm{120.0};
|
|
334
|
-
};
|
|
335
|
-
auto *beatState = new BeatState();
|
|
336
|
-
|
|
337
|
-
self.sourceNode = [[AVAudioSourceNode alloc] initWithRenderBlock:^OSStatus(BOOL *isSilence, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, AudioBufferList *outputData) {
|
|
338
|
-
double sr = sampleRate;
|
|
339
|
-
float *leftChannel = (float *)outputData->mBuffers[0].mData;
|
|
340
|
-
float *rightChannel = (outputData->mNumberBuffers > 1) ? (float *)outputData->mBuffers[1].mData : leftChannel;
|
|
341
|
-
|
|
342
|
-
for (AVAudioFrameCount i = 0; i < frameCount; i++) {
|
|
343
|
-
if (trans->advance(sr)) {
|
|
344
|
-
beatState->crossed.store(true);
|
|
345
|
-
beatState->beat.store(trans->getPosition());
|
|
346
|
-
beatState->bpm.store(trans->getTempo());
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
float sample = eng->getNextSample(sr);
|
|
350
|
-
leftChannel[i] = sample;
|
|
351
|
-
rightChannel[i] = sample;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return noErr;
|
|
355
|
-
}];
|
|
356
|
-
|
|
357
|
-
[self.audioEngine attachNode:self.sourceNode];
|
|
358
|
-
[self.audioEngine connect:self.sourceNode to:self.audioEngine.mainMixerNode format:format];
|
|
359
|
-
// Let the system decide the mixer→output format
|
|
360
|
-
[self.audioEngine connect:self.audioEngine.mainMixerNode to:self.audioEngine.outputNode format:nil];
|
|
361
|
-
|
|
362
|
-
[self.audioEngine prepare];
|
|
363
|
-
[self.audioEngine startAndReturnError:&error];
|
|
364
|
-
if (error) {
|
|
365
|
-
NSLog(@"[ExpoJuce] Error starting audio engine: %@", error);
|
|
366
|
-
} else {
|
|
367
|
-
NSLog(@"[ExpoJuce] Audio engine started successfully");
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Beat callback timer — polls at ~60Hz on main queue
|
|
371
|
-
self.beatTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
|
|
372
|
-
dispatch_source_set_timer(self.beatTimer, DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC, 1 * NSEC_PER_MSEC);
|
|
373
|
-
__weak JuceToneGenerator *weakSelf = self;
|
|
374
|
-
dispatch_source_set_event_handler(self.beatTimer, ^{
|
|
375
|
-
BeatCallback cb = weakSelf.beatCallback;
|
|
376
|
-
if (beatState->crossed.exchange(false) && cb) {
|
|
377
|
-
cb(beatState->beat.load(), beatState->bpm.load());
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
dispatch_resume(self.beatTimer);
|
|
381
|
-
|
|
382
|
-
} @catch (NSException *exception) {
|
|
383
|
-
NSLog(@"[ExpoJuce] CRASH in audio init: %@ — %@", exception.name, exception.reason);
|
|
384
|
-
}
|
|
295
|
+
// DIAGNOSTIC: no-op to isolate crash source.
|
|
296
|
+
// If app still crashes on pad tap, the problem is in setFrequency/noteOn.
|
|
297
|
+
// If app stops crashing, the problem is in AVAudioEngine setup.
|
|
298
|
+
NSLog(@"[ExpoJuce] initialize called (NO-OP diagnostic mode)");
|
|
385
299
|
}
|
|
386
300
|
|
|
387
301
|
- (void)shutdown {
|