我正在使用文本到语音,开始音频工作正常,但我无法停止它。这是我如何开始音频:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
[[self view] setNeedsDisplay];
[self synthesizeInBackground];
[queue waitUntilAllOperationsAreFinished];
[self setIsSpeaking: false];
[[self view] setNeedsDisplay];
});
在后台合成
- (void) synthesizeInBackground {
XLog(@"-----------------------------------entered");
queue = [[NSOperationQueue alloc] init];
XLog(@"queue: %@", queue);
operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(synthesize) object:nil];
XLog(@"operation: %@", operation);
[queue addOperation: operation];
}
合成
- (void)synthesize {
XLog(@"-----------------------------------entered");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
callback_userdata userdata;
NSError *error = nil;
self.paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
self.documentsDirectory = [self.paths objectAtIndex:0];
self.path = [self.documentsDirectory stringByAppendingPathComponent:@"readSearchresults.txt"];
IvonaStreamer *streamer = [[IvonaStreamer alloc] initWithVoice:voice withText:[NSString stringWithContentsOfFile:self.path encoding:NSUTF8StringEncoding error:&error] atSpeed:[NSNumber numberWithFloat:-1]];
//IvonaStreamer *streamer = [[IvonaStreamer alloc] initWithVoice:voice withText:@"Dies ist ein Testtext." atSpeed:[NSNumber numberWithFloat:-1]];
if (streamer == nil) {
XLog(@"Cannot start streamer");
[self setTtsError: @"Cannot start streamer"];
return;
}
userdata.speak = &(self->isSpeaking);
userdata.streamer = streamer;
#define NUM_BUFFERS 3
#define BUFFER_SIZE 22050
OSStatus err;
AudioQueueRef audioQueue;
//XLog(@"audioQueue: %d", audioQueue);
XLog(@"[voice getSampleRate]: %i", [voice getSampleRate]);
AudioStreamBasicDescription deviceFormat;
deviceFormat.mSampleRate = [voice getSampleRate];
deviceFormat.mFormatID = kAudioFormatLinearPCM;
deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
deviceFormat.mBytesPerPacket = 2;
deviceFormat.mFramesPerPacket = 1;
deviceFormat.mBytesPerFrame = 2;
deviceFormat.mChannelsPerFrame = 1;
deviceFormat.mBitsPerChannel = 16;
deviceFormat.mReserved = 0;
XLog(@"deviceFormat.mSampleRate: %f", deviceFormat.mSampleRate);
/*
XLog(@"deviceFormat.mSampleRate: %f", deviceFormat.mSampleRate);
XLog(@"deviceFormat.mFormatID: %lu", deviceFormat.mFormatID);
XLog(@"deviceFormat.mFormatFlags: %lu", deviceFormat.mFormatFlags);
XLog(@"deviceFormat.mBytesPerPacket %lu", deviceFormat.mBytesPerPacket);
XLog(@"deviceFormat.mFramesPerPacket %lu", deviceFormat.mFramesPerPacket);
XLog(@"deviceFormat.mBytesPerFrame %lu", deviceFormat.mBytesPerFrame);
XLog(@"deviceFormat.mChannelsPerFrame %lu", deviceFormat.mChannelsPerFrame);
XLog(@"deviceFormat.mBitsPerChannel %lu", deviceFormat.mBitsPerChannel);
XLog(@"deviceFormat.mReserved %lu", deviceFormat.mReserved);
*/
err = AudioQueueNewOutput(&deviceFormat,
AudioQueueCallback,
&userdata,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&audioQueue);
if (err != noErr) {
XLog(@"Cannot create audio output");
[self setTtsError: @"Cannot create audio output"];
[streamer stop];
return;
}
AudioQueueAddPropertyListener(audioQueue, kAudioQueueProperty_IsRunning,
AudioQueuePropertyListener, NULL);
for (int i = 0; i < NUM_BUFFERS; i++) {
AudioQueueBufferRef buffer;
err = AudioQueueAllocateBuffer(audioQueue, BUFFER_SIZE, &buffer);
if (err != noErr) {
XLog(@"Cannot allocate audio buffer");
[self setTtsError: @"Cannot allocate audio buffer"];
[streamer stop];
return;
}
AudioQueueCallback(&userdata, audioQueue, buffer);
}
err = AudioQueueStart(audioQueue, NULL);
if (err != noErr) {
XLog(@"Cannot start audio");
[self setTtsError: @"Cannot start audio"];
[streamer stop];
return;
}
CFRunLoopRun();
[streamer stop];
[pool release];
}
音频队列回调
void AudioQueueCallback(void *userData, AudioQueueRef audioQueue,
AudioQueueBufferRef buffer)
{
//XLog(@"-----------------------------------entered");
void *data = buffer->mAudioData;
UInt32 num_bytes = buffer->mAudioDataBytesCapacity;
//XLog(@"num_bytes: %lu", num_bytes);
UInt32 to_write = num_bytes / sizeof(short);
//XLog(@"to_write: %lu", to_write);
NSInteger num_samples;
//XLog(@"num_samples: %i", num_samples);
IvonaStreamer *streamer = ((callback_userdata*) userData)->streamer;
bool *enabled = ((callback_userdata*) userData)->speak;
//XLog(@"streamer.getWarnings: %@", streamer.getWarnings);
if(!*enabled) {
XLog(@"!*enabled");
AudioQueueStop(audioQueue, false);
}
num_samples = [streamer synthSamples:to_write toCArray:data];
//XLog(@"num_samples: %i", num_samples);
if (num_samples > 0) {
//XLog(@"num_samples > 0");
buffer->mAudioDataByteSize = num_samples * sizeof(short);
AudioQueueEnqueueBuffer(audioQueue, buffer, 0, NULL);
} else {
//XLog(@"! (num_samples > 0)");
AudioQueueStop(audioQueue, false);
}
}
AudioQueuePropertyListener
void AudioQueuePropertyListener(void *userData, AudioQueueRef audioQueue,
AudioQueuePropertyID id)
{
XLog(@"-----------------------------------entered");
UInt32 isRunning, size = sizeof(isRunning);
AudioQueueGetProperty(audioQueue, kAudioQueueProperty_IsRunning, &isRunning, &size);
if (isRunning == 0) {
XLog(@"isRunning == 0");
CFRunLoopStop(CFRunLoopGetCurrent());
}
if (isRunning != 0) {
XLog(@"nicht null#######");
}
}
我尝试停止其他方法(UIAlertView 委托方法):
if (alertView.tag == 997) {
if (buttonIndex == 0) {
XLog(@"vorlesen abbrechen geklickt.");
[queue cancelAllOperations];
AudioQueueRef audioQueue;
//AudioQueueDispose(audioQueue, false);
AudioQueueStop(audioQueue, false);
}
我正在取消所有操作并调用 AudioQueueDispose,也尝试使用 AudioQueueStop,但这里没有任何效果。
所以我的问题是,我怎样才能在这里停止音频?