以数值显示SPL级别而不是改变颜色强度

时间:2017-03-14 02:53:56

标签: ios objective-c uiview core-audio avaudiosession

我正在尝试为iOS中的uni项目开发SPL仪表,我一直在关注如何获取音频输入和显示输入级别的在线教程,但本教程将输入显示为不同强度的颜色和也是在RMS值,而不是峰值。我之前找到了两篇与之相关的帖子,但是他们没有足够的信息来帮助,而且作为堆叠溢出的新手,我无法要求对所提供的答案提供进一步的支持。

Previous Post 1

Previous Post 2

我一直关注的项目教程是在Objective-C而不是Swift中运行,因为它是一个旧的视频集合,但它(几乎)我需要它,所以没有尝试改为swift,直到我理解我正在做什么以及我为什么这样做。

以下是录制和输入级别监控的完整代码:

//Lynda.Com Tutorial Project


#import "ViewController.h"

@import AudioToolbox;
@import AVFoundation;

#define kOutputBus 0
#define kInputBus 1

@interface ViewController ()

@property (nonatomic,weak) IBOutlet UIView *indicatorView;

@end

@implementation ViewController

static AudioComponentInstance audioUnit;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self setupAudio];
}

- (void) setupAudio {
    AudioComponentDescription desc;

    desc.componentType = kAudioUnitType_Output;
    desc.componentSubType = kAudioUnitSubType_RemoteIO;
    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    desc.componentFlags = 0;
    desc.componentFlagsMask = 0;

    AudioComponent comp = AudioComponentFindNext(NULL, &desc);

    OSStatus status = AudioComponentInstanceNew(comp, &audioUnit);
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }

    AudioStreamBasicDescription audioFormat;

    audioFormat.mSampleRate = 44100.00;
    audioFormat.mFormatID = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket = 1;
    audioFormat.mChannelsPerFrame = 1;
    audioFormat.mBitsPerChannel = 16;
    audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * sizeof(SInt16);
    audioFormat.mBytesPerPacket = audioFormat.mFramesPerPacket * audioFormat.mBytesPerFrame;

    UInt32 flag = 1;
    status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag));
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }

    flag = 0;
    status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag));
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }

    status = AudioUnitSetProperty(audioUnit , kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &audioFormat, sizeof(audioFormat));
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }

    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = recordingCallback;
    callbackStruct.inputProcRefCon = (__bridge void*)self;

    status = AudioUnitSetProperty(audioUnit , kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callbackStruct, sizeof(callbackStruct));
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }

    status = AudioUnitInitialize(audioUnit);
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }

}

static OSStatus recordingCallback(

                                  void *inRefCon,
                                  AudioUnitRenderActionFlags *ioActionFlags,
                                  const AudioTimeStamp *inTimeStamp,
                                  UInt32 inBusNumber,
                                  UInt32 inNumberFrames,
                                  AudioBufferList *ioData

                            ) {

    AudioBuffer buffer;

    buffer.mNumberChannels = 1;
    buffer.mDataByteSize = inNumberFrames * sizeof(SInt16);
    buffer.mData = malloc(buffer.mDataByteSize);

    AudioBufferList bufferList;
    bufferList.mNumberBuffers = 1;
    bufferList.mBuffers[0] = buffer;

    OSStatus status = AudioUnitRender(audioUnit , ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
    if (status != noErr) {
        printf("Error\n");
        return -1;
    }

    SInt16 *frameBuffer = buffer.mData;

    double totalAmplitude = 0;

    for (int i = 0; i < inNumberFrames; i++) {
        //printf("%i\n",frameBuffer[i]);
        totalAmplitude += frameBuffer[i] * frameBuffer[i];
    }

    totalAmplitude /= inNumberFrames;

    totalAmplitude = sqrt(totalAmplitude);

    float alphaFloat = totalAmplitude / (float)SHRT_MAX * 2;

    dispatch_async(dispatch_get_main_queue(), ^{
        ViewController *viewController = (__bridge ViewController*)inRefCon;
        viewController.indicatorView.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:alphaFloat];
    });

    return noErr;
}

- (IBAction)recordButtonPressed:(id)sender {
    NSError *error;
    [[AVAudioSession sharedInstance] setActive:YES error:&error];
    if (error != nil) {
        NSAssert(error == nil, @"Error");
    }
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:&error];
    if (error != nil) {
        NSAssert(error == nil, @"Error");
    }

    [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
        if (granted) {
            OSStatus status = AudioOutputUnitStart(audioUnit);
            if (status != noErr) {
                NSAssert(status == noErr,@"Error");
            }
        } else {
            NSAssert(NO, @"Error");
        }
    }];
}

- (IBAction)stopButtonPressed:(id)sender {
    OSStatus status = AudioOutputUnitStop(audioUnit);
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }
    NSError *error;
    [[AVAudioSession sharedInstance] setActive:NO error:&error];
    if (error != nil) {
        NSAssert(error == nil, @"Error");
    }
    self.indicatorView.backgroundColor = [UIColor clearColor];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) dealloc {
    OSStatus status = AudioComponentInstanceDispose(audioUnit);
    if (status != noErr) {
        NSAssert(status == noErr,@"Error");
    }
}

@end

我需要帮助理解,因为我相信这段代码:

dispatch_async(dispatch_get_main_queue(), ^{
    ViewController *viewController = (__bridge ViewController*)inRefCon;
    viewController.indicatorView.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:alphaFloat];

这是UIView被告知显示不同强度的红色的地方,我想要的是将其改变为不同的数字。

RMS到dBSPL的值不是问题,它在运行应用程序中的红框内显示为不断变化的值,我可以通过一些帮助真正做到,所有帮助都非常值得赞赏前进!<​​/ p>

谢谢,

克里斯

1 个答案:

答案 0 :(得分:0)

您要显示的值位于变量alphaFloat中。您需要向ViewController添加UILabel属性,您可以将其称为dBSPLView。然后在更改viewController.indicatorView.backgroundColor的地方你会做这样的事情:

viewController.dBSPLView.text = [NSString stringWithFormat:@"%f", alphaFloat];