您的位置:首页 > 移动开发 > IOS开发

iOS ijkplayer Audio Unit 播放音频

2017-05-31 15:38 2496 查看
设置AudioUnit的播放的方法参考上一篇文章 此处不再多说

这里给出AudioUnit的代码请查阅

/*
* IJKSDLAudioUnitController.h
*
* Copyright (c) 2013 Bilibili
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie *
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#import <Foundation/Foundation.h>

#include "ijksdl/ijksdl_aout.h"

@interface IJKSDLAudioUnitController : NSObject

- (id)initWithAudioSpec:(const SDL_AudioSpec *)aSpec;

- (void)play;
- (void)pause;
- (void)flush;
- (void)stop;
- (void)close;

- (void)setPlaybackRate:(float)playbackRate;
- (void)setPlaybackVolume:(float)playbackVolume;
- (double)get_latency_seconds;

@property (nonatomic, readonly) SDL_AudioSpec spec;

@end


/*
* IJKSDLAudioUnitController.m
*
* Copyright (c) 2013 Bilibili
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie *
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#import "IJKSDLAudioUnitController.h"
#import "IJKSDLAudioKit.h"
#include "ijksdl/ijksdl_log.h"

#import <AVFoundation/AVFoundation.h>

@implementation IJKSDLAudioUnitController {
AudioUnit _auUnit;
BOOL _isPaused;
}

- (id)initWithAudioSpec:(const SDL_AudioSpec *)aSpec
{
self = [super init];
if (self) {
if (aSpec == NULL) {
self = nil;
return nil;
}
_spec = *aSpec;

if (aSpec->format != AUDIO_S16SYS) {
NSLog(@"aout_open_audio: unsupported format %d\n", (int)aSpec->format);
return nil;
}

if (aSpec->channels > 6) {
NSLog(@"aout_open_audio: unsupported channels %d\n", (int)aSpec->channels);
return nil;
}

AudioComponentDescription desc;
IJKSDLGetAudioComponentDescriptionFromSpec(&_spec, &desc);

AudioComponent auComponent = AudioComponentFindNext(NULL, &desc);
if (auComponent == NULL) {
ALOGE("AudioUnit: AudioComponentFindNext failed");
self = nil;
return nil;
}

AudioUnit auUnit;
OSStatus status = AudioComponentInstanceNew(auComponent, &auUnit);
if (status != noErr) {
ALOGE("AudioUnit: AudioComponentInstanceNew failed");
self = nil;
return nil;
}

UInt32 flag = 1;
status = AudioUnitSetProperty(auUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
0,
&flag,
sizeof(flag));
if (status != noErr) {
ALOGE("AudioUnit: failed to set IO mode (%d)", (int)status);
}

/* Get the current format */
_spec.format = AUDIO_S16SYS;
_spec.channels = 2;
AudioStreamBasicDescription streamDescription;
IJKSDLGetAudioStreamBasicDescriptionFromSpec(&_spec, &streamDescription);

/* Set the desired format */
UInt32 i_param_size = sizeof(streamDescription);
status = AudioUnitSetProperty(auUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&streamDescription,
i_param_size);
if (status != noErr) {
ALOGE("AudioUnit: failed to set stream format (%d)", (int)status);
self = nil;
return nil;
}

/* Retrieve actual format */
status = AudioUnitGetProperty(auUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&streamDescription,
&i_param_size);
if (status != noErr) {
ALOGE("AudioUnit: failed to verify stream format (%d)\n", (int)status);
}

AURenderCallbackStruct callback;
callback.inputProc = (AURenderCallback) RenderCallback;
callback.inputProcRefCon = (__bridge void*) self;
status = AudioUnitSetProperty(auUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0, &callback, sizeof(callback));
if (status != noErr) {
ALOGE("AudioUnit: render callback setup failed (%d)\n", (int)status);
self = nil;
return nil;
}

SDL_CalculateAudioSpec(&_spec);

/* AU initiliaze */
status = AudioUnitInitialize(auUnit);
if (status != noErr) {
ALOGE("AudioUnit: AudioUnitInitialize failed (%d)\n", (int)status);
self = nil;
return nil;
}

_auUnit = auUnit;
}
return self;
}

- (void)dealloc
{
[self close];
}

- (void)play
{
if (!_auUnit)
return;

_isPaused = NO;
NSError *error = nil;
if (NO == [[AVAudioSession sharedInstance] setActive:YES error:&error]) {
NSLog(@"AudioUnit: AVAudioSession.setActive(YES) failed: %@\n", error ? [error localizedDescription] : @"nil");
}

OSStatus status = AudioOutputUnitStart(_auUnit);
if (status != noErr)
NSLog(@"AudioUnit: AudioOutputUnitStart failed (%d)\n", (int)status);
}

- (void)pause
{
if (!_auUnit)
return;

_isPaused = YES;
OSStatus status = AudioOutputUnitStop(_auUnit);
if (status != noErr)
ALOGE("AudioUnit: failed to stop AudioUnit (%d)\n", (int)status);
}

- (void)flush
{
if (!_auUnit)
return;

AudioUnitReset(_auUnit, kAudioUnitScope_Global, 0);
}

- (void)stop
{
if (!_auUnit)
return;

OSStatus status = AudioOutputUnitStop(_auUnit);
if (status != noErr)
ALOGE("AudioUnit: failed to stop AudioUnit (%d)", (int)status);
}

- (void)close
{
[self stop];

if (!_auUnit)
return;

AURenderCallbackStruct callback;
memset(&callback, 0, sizeof(AURenderCallbackStruct));
AudioUnitSetProperty(_auUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &callback,
sizeof(callback));

AudioComponentInstanceDispose(_auUnit);
_auUnit = NULL;
}

- (void)setPlaybackRate:(float)playbackRate
{
//    if (fabsf(playbackRate - 1.0f) <= 0.000001) {
//        UInt32 propValue = 1;
//        AudioQueueSetProperty(_audioQueueRef, kAudioQueueProperty_TimePitchBypass, &propValue, sizeof(propValue));
//        AudioQueueSetParameter(_audioQueueRef, kAudioQueueParam_PlayRate, 1.0f);
//    } else {
//        UInt32 propValue = 0;
//        AudioQueueSetProperty(_audioQueueRef, kAudioQueueProperty_TimePitchBypass, &propValue, sizeof(propValue));
//        AudioQueueSetParameter(_audioQueueRef, kAudioQueueParam_PlayRate, playbackRate);
//    }
}

- (void)setPlaybackVolume:(float)playbackVolume
{
//    float aq_volume = playbackVolume;
//    if (fabsf(aq_volume - 1.0f) <= 0.000001) {
//        AudioQueueSetParameter(_audioQueueRef, kAudioQueueParam_Volume, 1.f);
//    } else {
//        AudioQueueSetParameter(_audioQueueRef, kAudioQueueParam_Volume, aq_volume);
//    }
}

//- (double)get_latency_seconds
//{
//    return ((double)(kIJKAudioQueueNumberBuffers)) * _spec.samples / _spec.freq;
//}

- (double)get_latency_seconds
{
return (double) _spec.samples / _spec.freq;
}

static OSStatus RenderCallback(void                        *inRefCon,
AudioUnitRenderActionFlags  *ioActionFlags,
const AudioTimeStamp        *inTimeStamp,
UInt32                      inBusNumber,
UInt32                      inNumberFrames,
AudioBufferList             *ioData)
{
@autoreleasepool {
IJKSDLAudioUnitController* auController = (__bridge IJKSDLAudioUnitController *) inRefCon;

if (!auController || auController->_isPaused) {
for (UInt32 i = 0; i < ioData->mNumberBuffers; i++) {
AudioBuffer *ioBuffer = &ioData->mBuffers[i];
memset(ioBuffer->mData, auController.spec.silence, ioBuffer->mDataByteSize);
}
return noErr;
}

for (int i = 0; i < (int)ioData->mNumberBuffers; i++) {
AudioBuffer *ioBuffer = &ioData->mBuffers[i];
(*auController.spec.callback)(auController.spec.userdata, ioBuffer->mData, ioBuffer->mDataByteSize);
}

return noErr;
}
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: