我目前正在开发一款应用程序,该应用程序使用Gracenote Mobile Client创建指纹以及识别我正在收听的音乐。我已经在我的项目中成功实现了它,但现在由于业务需求,我将使用Gracenote录制的音频进行不同的处理。
重点是:由于GNAudioSourceMic封装了整个麦克风录音操作,例如startRecording / stopRecording,因此我无法访问麦克风原始音频。
这是我使用的代码:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setNeedsStatusBarAppearanceUpdate];
[self setupUI];
@try {
self.config = [GNConfig init:GRACENOTE_CLIENTID];
}
@catch (NSException * e) {
NSLog(@"%s clientId can't be nil or the empty string",__PRETTY_FUNCTION__);
[self.view setUserInteractionEnabled:FALSE];
return;
}
// Debug is disabled in the GUI by default
#ifdef DEBUG
[self.config setProperty:@"debugEnabled" value:@"1"];
#else
[self.config setProperty:@"debugEnabled" value:@"0"];
#endif
[self.config setProperty:@"lookupmodelocalonly" value:@"0"];
// -------------------------------------------------------------------------------
//Init AudioSource to Start Recording.
// -------------------------------------------------------------------------------
self.recognizeFromPCM = [GNRecognizeStream gNRecognizeStream:self.config];
self.audioConfig = [GNAudioConfig gNAudioConfigWithSampleRate:44100 bytesPerSample:2 numChannels:1];
self.objAudioSource = [GNAudioSourceMic gNAudioSourceMic:self.audioConfig];
self.objAudioSource.delegate=self;
NSError *err;
RecognizeStreamOperation *op = [RecognizeStreamOperation recognizeStreamOperation:self.config];
op.viewControllerDelegate = self;
err = [self.recognizeFromPCM startRecognizeSession:op audioConfig:self.audioConfig];
if (err) {
NSLog(@"ERROR: %@",[err localizedDescription]);
}
[self.objAudioSource startRecording];
[self performSelectorInBackground:@selector(setUpRecognizePCMSession) withObject:nil];
}
-(void) startRecordMicrophone{
#ifdef DEBUG
NSLog(@"%s startRecording",__PRETTY_FUNCTION__);
#endif
NSError *error;
error = [self.recognizeFromPCM idNow];
if (error) {
NSLog(@"ERROR: %@",[error localizedDescription]);
}
}
是否有人接触到与上述相同的需求?
提前致谢
答案 0 :(得分:0)
昨天经过大量的谷歌搜索后,我想出了一个解决方案,这个解决方案不是我以前所期待的,但它的效果和我想要的一样好。我决定自己录制iOS麦克风,然后在Grancenote SDK上调用一个方法来识别我刚录制的内容。
这对我有用。
<强> MicrophoneInput.h 强>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface MicrophoneInput : UIViewController {
AVAudioPlayer *audioPlayer;
AVAudioRecorder *audioRecorder;
int recordEncoding;
enum
{
ENC_AAC = 1,
ENC_ALAC = 2,
ENC_IMA4 = 3,
ENC_ILBC = 4,
ENC_ULAW = 5,
ENC_PCM = 6,
} encodingTypes;
}
-(IBAction) startRecording;
-(IBAction) stopRecording;
@end
<强> MicrophoneInput.m 强>
#import "MicrophoneInput.h"
@implementation MicrophoneInput
- (void)viewDidLoad
{
[super viewDidLoad];
recordEncoding = ENC_PCM;
}
-(IBAction) startRecording
{
NSLog(@"startRecording");
[audioRecorder release];
audioRecorder = nil;
// Init audio with record capability
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] initWithCapacity:10];
recordSettings[AVFormatIDKey] = @(kAudioFormatLinearPCM);
recordSettings[AVSampleRateKey] = @8000.0f;
recordSettings[AVNumberOfChannelsKey] = @1;
recordSettings[AVLinearPCMBitDepthKey] = @16;
recordSettings[AVLinearPCMIsBigEndianKey] = @NO;
recordSettings[AVLinearPCMIsFloatKey] = @NO;
//set the export session's outputURL to <Documents>/output.caf
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSURL* outURL = [NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:@"output.caf"]];
[[NSFileManager defaultManager] removeItemAtURL:outURL error:nil];
NSLog(@"url loc is %@", outURL);
NSError *error = nil;
audioRecorder = [[ AVAudioRecorder alloc] initWithURL:outURL settings:recordSettings error:&error];
if ([audioRecorder prepareToRecord] == YES){
[audioRecorder record];
}else {
int errorCode = CFSwapInt32HostToBig ([error code]);
NSLog(@"Error: %@ [%4.4s])" , [error localizedDescription], (char*)&errorCode);
}
NSLog(@"recording");
}
-(IBAction) stopRecording
{
NSLog(@"stopRecording");
[audioRecorder stop];
NSLog(@"stopped");
}
- (void)dealloc
{
[audioPlayer release];
[audioRecorder release];
[super dealloc];
}
@end
Obs。:如果您正在使用ARC,请不要忘记在Compiling BuildPhase上添加-fno-objc-arc编译器标志,如下所示。
<强> YourViewController.h 强>
//Libraries
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
//Echonest Codegen
#import "MicrophoneInput.h"
//GracenoteMusic
#import <GracenoteMusicID/GNRecognizeStream.h>
#import <GracenoteMusicID/GNAudioSourceMic.h>
#import <GracenoteMusicID/GNAudioConfig.h>
#import <GracenoteMusicID/GNCacheStatus.h>
#import <GracenoteMusicID/GNConfig.h>
#import <GracenoteMusicID/GNSampleBuffer.h>
#import <GracenoteMusicID/GNOperations.h>
#import <GracenoteMusicID/GNSearchResponse.h>
@interface YourViewController : UIViewController<GNSearchResultReady>
@end
<强> YourViewController.m 强>
#import "YourViewController.h"
@interface YourViewController ()
//Record
@property(strong,nonatomic) MicrophoneInput* recorder;
@property (strong,nonatomic) GNConfig *config;
@end
@implementation YourViewController
#pragma mark - UIViewController lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.recorder = [[MicrophoneInput alloc] init];
@try {
self.config = [GNConfig init:GRACENOTE_CLIENTID];
}
@catch (NSException * e) {
NSLog(@"%s clientId can't be nil or the empty string",__PRETTY_FUNCTION__);
[self.view setUserInteractionEnabled:FALSE];
return;
}
// Debug is disabled in the GUI by default
#ifdef DEBUG
[self.config setProperty:@"debugEnabled" value:@"1"];
#else
[self.config setProperty:@"debugEnabled" value:@"0"];
#endif
[self.config setProperty:@"lookupmodelocalonly" value:@"0"];
}
-(void)viewDidAppear:(BOOL)animated{
[self performSelectorInBackground:@selector(startRecordMicrophone) withObject:nil];
}
-(void) startRecordMicrophone{
#ifdef DEBUG
NSLog(@"%s startRecording",__PRETTY_FUNCTION__);
#endif
[self.recorder startRecording];
[self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO];
}
-(void) stopRecordMicrophone{
#ifdef DEBUG
NSLog(@"%s stopRecording",__PRETTY_FUNCTION__);
#endif
[self.recorder stopRecording];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSString *filePath =[documentsDirectory stringByAppendingPathComponent:@"output.caf"];
NSData* sampleData = [[NSData alloc] initWithContentsOfFile:filePath];
GNSampleBuffer *sampleBuffer = [GNSampleBuffer gNSampleBuffer:sampleData numChannels:1 sampleRate:8000];
[GNOperations recognizeMIDStreamFromPcm:self config:self.config sampleBuffer:sampleBuffer];
}
#pragma mark - UI methods
-(void)makeMyProgressBarMoving {
float actual = [self.progressBar progress];
if (actual < 1) {
[self.loadingAnimationView showNextLevel];
self.progressBar.progress = actual + 0.0125;
[NSTimer scheduledTimerWithTimeInterval:0.25f target:self selector:@selector(makeMyProgressBarMoving) userInfo:nil repeats:NO];
}
else{
self.progressBar.hidden = YES;
[self stopRecordMicrophone];
}
}
#pragma mark - GNSearchResultReady methods
- (void) GNResultReady:(GNSearchResult*)result{
NSLog(@"%s",__PRETTY_FUNCTION__);
}
@end
有关MicrophoneInput解决方案的信息,请转到Brian Whitman和Echo Nest Library。
希望能帮助那些面临同样情况的人。
干杯
答案 1 :(得分:0)
即使使用附带的GnMic类,Gracenote SDK也能提供对音频数据的访问。 GnMic类定义了一个GnMicDelegate协议,您可以使用该协议在新的音频缓冲区可用时收到通知。你必须:
<强> GnViewController.h 强>
将GnMicDelegate协议添加到类定义
@interface GnViewController : UIViewController<CLLocationManagerDelegate, UITableViewDataSource, UITableViewDelegate, UINavigationBarDelegate, UIActionSheetDelegate, GnMicDelegate>
<强> GnViewController.m 强>
将您的类指定为GnMic实例的委托
self.gnMic = [[GnMic alloc] initWithSampleRate: 44100 bitsPerChannel: 16 numberOfChannels: 1 delegate:nil];
self.gnMic.gnMicDelegate = self;
实施协议方法。每次有新的音频缓冲区可用于处理时,都会调用此方法
- (void) audioBufferDidBecomeReady:(NSData *)samples {
// Do something with the audio samples
}