Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed Crash when launching from background while audio playing; Ability to manage Sample Rate #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 39 additions & 28 deletions Novocaine iOS Example/ViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,30 @@ - (void)viewWillAppear:(BOOL)animated

ringBuffer = new RingBuffer(32768, 2);
audioManager = [Novocaine audioManager];
// [audioManager routeToSpeaker];


// Basic playthru example
// [audioManager setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
// float volume = 0.5;
// vDSP_vsmul(data, 1, &volume, data, 1, numFrames*numChannels);
// ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels);
// }];
//
//
// [audioManager setOutputBlock:^(float *outData, UInt32 numFrames, UInt32 numChannels) {
// ringBuffer->FetchInterleavedData(outData, numFrames, numChannels);
// }];

// Basic IO example
[audioManager setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
// *data - data from microphone

// STEP 1. Convert *data from PCM format to iLBC
// ...

// STEP 2. Convert back to PCM
// ...

// save data to queue
ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels);
}];

[audioManager setOutputBlock:^(float *outData, UInt32 numFrames, UInt32 numChannels) {
// Play data
ringBuffer->FetchInterleavedData(outData, numFrames, numChannels);
}];




// MAKE SOME NOOOOO OIIIISSSEEE
Expand Down Expand Up @@ -165,23 +176,23 @@ - (void)viewWillAppear:(BOOL)animated
// }];


// AUDIO FILE READING OHHH YEAHHHH
// ========================================
NSURL *inputFileURL = [[NSBundle mainBundle] URLForResource:@"TLC" withExtension:@"mp3"];

fileReader = [[AudioFileReader alloc]
initWithAudioFileURL:inputFileURL
samplingRate:audioManager.samplingRate
numChannels:audioManager.numOutputChannels];

[fileReader play];
fileReader.currentTime = 30.0;

[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
{
[fileReader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels];
NSLog(@"Time: %f", fileReader.currentTime);
}];
// // AUDIO FILE READING OHHH YEAHHHH
// // ========================================
// NSURL *inputFileURL = [[NSBundle mainBundle] URLForResource:@"TLC" withExtension:@"mp3"];
//
// fileReader = [[AudioFileReader alloc]
// initWithAudioFileURL:inputFileURL
// samplingRate:audioManager.samplingRate
// numChannels:audioManager.numOutputChannels];
//
// [fileReader play];
// fileReader.currentTime = 30.0;
//
// [audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
// {
// [fileReader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels];
// NSLog(@"Time: %f", fileReader.currentTime);
// }];


// AUDIO FILE WRITING YEAH!
Expand Down
4 changes: 4 additions & 0 deletions Novocaine/Novocaine.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,5 +180,9 @@ typedef void (^InputBlock)(float *data, UInt32 numFrames, UInt32 numChannels);
- (void)checkAudioSource;
#endif

- (void)routeToSpeaker;
- (void)routeToHeadphone;
-(void) routeSpeaker;
-(void) routeToDefaultSpeaker;

@end
70 changes: 60 additions & 10 deletions Novocaine/Novocaine.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
#define kOutputBus 0
#define kDefaultDevice 999999

#define sampleRateT 8000.0
#define IOBufferDuration 0.0232*2
//#define sampleRateT 22050.0
//#define sampleRateT 44100.0

#import "TargetConditionals.h"

static Novocaine *audioManager = nil;
Expand Down Expand Up @@ -233,10 +238,13 @@ - (void)setupAudio
// Set the buffer size, this will affect the number of samples that get rendered every time the audio callback is fired
// A small number will get you lower latency audio, but will make your processor work harder
#if !TARGET_IPHONE_SIMULATOR
Float32 preferredBufferSize = 0.0232;
Float32 preferredBufferSize = IOBufferDuration;
CheckError( AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize), "Couldn't set the preferred buffer duration");
#endif

Float64 F64sampleRate = sampleRateT;
CheckError( AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(F64sampleRate), &F64sampleRate), "Couldn't set the preferred sample rate");


// Set the audio session active
CheckError( AudioSessionSetActive(YES), "Couldn't activate the audio session");
Expand Down Expand Up @@ -271,7 +279,7 @@ - (void)setupAudio
#elif defined (USING_IOS)
AudioComponentDescription inputDescription = {0};
inputDescription.componentType = kAudioUnitType_Output;
inputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
inputDescription.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
inputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;

#endif
Expand Down Expand Up @@ -351,8 +359,8 @@ - (void)setupAudio
"Couldn't get the hardware output stream format");

// TODO: check this works on iOS!
inputFormat.mSampleRate = 44100.0;
outputFormat.mSampleRate = 44100.0;
inputFormat.mSampleRate = sampleRateT;
outputFormat.mSampleRate = sampleRateT;
self.samplingRate = inputFormat.mSampleRate;
self.numBytesPerSample = inputFormat.mBitsPerChannel / 8;

Expand Down Expand Up @@ -555,8 +563,6 @@ - (void)setupAudio
#if defined ( USING_OSX )
CheckError(AudioUnitInitialize(outputUnit), "Couldn't initialize the output unit");
#endif



}

Expand Down Expand Up @@ -829,18 +835,18 @@ - (void)checkSessionProperties
UInt32 newNumChannels;
CheckError( AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &size, &newNumChannels), "Checking number of input channels");
self.numInputChannels = newNumChannels;
// self.numInputChannels = 1;
NSLog(@"We've got %lu input channels", self.numInputChannels);
if(self.numInputChannels > 1){
self.numInputChannels = 1;
}


// Check the number of input channels.
// Find the number of channels
CheckError( AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &size, &newNumChannels), "Checking number of output channels");
self.numOutputChannels = newNumChannels;
// self.numOutputChannels = 1;
NSLog(@"We've got %lu output channels", self.numOutputChannels);


// Get the hardware sampling rate. This is settable, but here we're only reading.
Float64 currentSamplingRate;
size = sizeof(currentSamplingRate);
Expand All @@ -857,13 +863,13 @@ void sessionInterruptionListener(void *inClientData, UInt32 inInterruption) {
if (inInterruption == kAudioSessionBeginInterruption) {
NSLog(@"Begin interuption");
sm.inputAvailable = NO;
[sm pause];
}
else if (inInterruption == kAudioSessionEndInterruption) {
NSLog(@"End interuption");
sm.inputAvailable = YES;
[sm play];
}

}

#endif
Expand All @@ -887,6 +893,50 @@ - (void)selectAudioDevice:(AudioDeviceID)deviceID
#endif



-(void)routeToSpeaker
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; // 1

CheckError( AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
sizeof(kAudioSessionCategory_PlayAndRecord),
&audioRouteOverride
), "err1 - speaker");
}
-(void)routeToHeadphone
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None;

CheckError( AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
sizeof(kAudioSessionCategory_PlayAndRecord),
&audioRouteOverride
), "err2 - headphone");
}

-(void)routeSpeaker
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; // 1

AudioSessionSetProperty (
kAudioSessionProperty_OverrideAudioRoute, // 2
sizeof (audioRouteOverride), // 3
&audioRouteOverride // 4
);

}

-(void)routeToDefaultSpeaker
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None; // 1

AudioSessionSetProperty (
kAudioSessionProperty_OverrideAudioRoute, // 2
sizeof (audioRouteOverride), // 3
&audioRouteOverride // 4
);
}


#pragma mark - Convenience Methods
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
Expand Down
4 changes: 4 additions & 0 deletions Novocaine/RingBuffer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@
mLastWrittenIndex[iChannel] = (mLastWrittenIndex[iChannel] + numFrames) % (mSizeOfBuffer);
mNumUnreadFrames[iChannel] = (mNumUnreadFrames[iChannel] + numFrames);
if (mNumUnreadFrames[iChannel] >= mSizeOfBuffer) mNumUnreadFrames[iChannel] = mSizeOfBuffer;


// NSLog(@"mLastWrittenIndex[iChannel] %lld", mLastWrittenIndex[iChannel]);

}


Expand Down