iOSのSystemSoundID(システムサウンドの再生)とAVAudioRecorder(録音)
Systemsoundid
最初にSystemSoundIDを紹介します。
SystemSoundIDの概要
AudioToolbox.framework is a C-based framework that uses it to play sound effects by registering short audio to the System Sound Service. System Sound Service is a simple, low-level sound playback service, but it also has some limitations:
短いサウンドファイルを再生する(バイブレーションをサポート)
短い音(30秒未満)を再生するために使用できます
-
このインターフェイスは、レベル、位置、ループ、時間制御、および同時再生をサポートしていません。同時に、1つのサウンドしか再生できません。
------------注:データはPCMまたはIMA4形式である必要があります
----------注:オーディオファイルは、.caf、.aif、.wavのいずれかにパッケージ化する必要があります(これは公式ドキュメントであり、実際のテストでは.mp3も再生できることがわかりました)
メインAPI:
オブジェクトを作成します。
OSStatus AudioServicesCreateSystemSoundID ( CFURLRef __nonnull inFileURL,SystemSoundID * __nonnull outSystemSoundID )
オブジェクトを破壊します:
OSStatus AudioServicesDisposeSystemSoundID ( SystemSoundID inSystemSoundID)
音を鳴らす:(合計2つ)
振動効果で遊ぶ:
void AudioServicesPlayAlertSound ( SystemSoundID inSystemSoundID ) void AudioServicesPlaySystemSound ( SystemSoundID inSystemSoundID )
再生が完了した後に実行される操作:(兄弟の4つのパラメーターがC言語関数である場合)
OSStatus AudioServicesAddSystemSoundCompletion ( SystemSoundIDinSystemSoundID, CFRunLoopRef __nullable inRunLoop, CFStringRef __nullableinRunLoopMode, AudioServicesSystemSoundCompletionProc __nonnullinCompletionRoutine, void * __nullable inClientData )
詳細な使用法:
詳細な使用法:
//1. Get the full path of the sound file NSURL *url=[[NSBundle mainBundle] URLForResource:@'4.wav' withExtension:nil] //2. Load the sound file and create a sound ID (SoundID, one ID corresponds to one sound file) SystemSoundID soundID = 0 AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &soundID) / / Pass the ID of the sound file that needs to be destroyed to it can be destroyed //AudioServicesDisposeSystemSoundID(soundID) // The soundCompleteCallback function executed after the completion of playback AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, soundCompleteCallback, NULL) //3. Playing sound files / / The following two functions can be used to play sound files, the first function is accompanied by vibration effects AudioServicesPlayAlertSound(soundID) //AudioServicesPlaySystemSound() #pragma mark - function executed after the completion of playback void soundCompleteCallback() { NSLog (@'play completed') }
AVAudioRecorderの概要:
テープレコーダーを使用すると、次のことができます。
Record until the user stops recording
Record sound at a specific time
Pause and resume recording
Record the input audio level data that you can use to provide metering levels
説明:
レコーダを作成するときは、指定したパスに加えて記録設定情報を指定する必要があります。これは、レコーダが記録ファイルの形式、サンプリングレート、チャネル数、およびサンプルポイントあたりのビット数を認識している必要があるためです。ただし、すべての情報を設定する必要はありません。通常は、いくつかの一般的な設定のみです。録音設定については、ヘルプドキュメントの「AVFoundationオーディオ設定定数」を参照してください。
————注:録音時にAVAudioSessionを設定する必要があります。設定しないと、録音できません。
/ ***オーディオセッションを設定します* /
-(void)setAudioSession{ AVAudioSession *audioSession=[AVAudioSession sharedInstance]
//録音後に録音を再生できるように、ステータスを再生および録音するように設定します
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil] [audioSession setActive:YES error:nil] }
メインAPI:
初期化:
- (instancetype nullable)initWithURL:(NSURL * nonnull)url settings:(NSDictionary * nonnull)settings error:(NSError * nullable * nullable)outError
記録する準備ができました:
- (BOOL)prepareToRecord
録音:
- (BOOL)record
タイムアウト:
- (void)pause
やめる:
- (void)stop
特定の時間に録音を開始します。
- (BOOL)recordAtTime:(NSTimeInterval)time
録音設定:(特に重要)
@property(readonly) NSDictionary *settings
音声測定を開始するかどうか:
/ / Whether to enable audio measurement, the default is NO, once the audio measurement is enabled, the measurement value can be updated by the updateMeters method @property(getter=isMeteringEnabled) BOOL meteringEnabled
音声測定値の更新:
//Update the audio measurement value. Note that if you want to update the audio measurement value, you must set the meteringEnabled to YES. You can get the audio decibel and other information instantly through the audio measurement value. - (void)updateMeters
指定されたチャネルのデシベル値を取得します。
//Get the decibel peak of the specified channel. Note that if you want to get the decibel peak, you must call the updateMeters method before this. - (float)peakPowerForChannel:(NSUInteger)channelNumber
コードの実装を見てみましょう。
// // ViewController.m // SystemSoundle plays audio // // Created by dlios on 15/12/8. // Copyright © 2015 PFG. All rights reserved. // #import 'ViewController.h' #import @interface ViewController () @property (nonatomic, strong)UIButton *playerButton @property (nonatomic, strong)UIButton *recorderButton @property (nonatomic, strong)UIButton *avAudionButton @property (nonatomic, strong)UIImageView *imageView @property (nonatomic, strong)UIImageView *imageViewSound @property (nonatomic, strong)AVAudioRecorder *reverb @property (nonatomic, strong)NSMutableDictionary *recordSetting @property (nonatomic, strong)AVAudioPlayer *player @property (nonatomic, strong)NSString *path @property (nonatomic, strong)NSTimer *timer @property (nonatomic, assign)double lowPassResults @property (nonatomic, strong)NSArray *arrayImage @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad] // Do any additional setup after loading the view, typically from a nib. self.view.backgroundColor = [UIColor grayColor] AVAudioSession *session = [[AVAudioSession alloc] init] / / Set the working mode of the session [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil] [self creatControl] / / Set the format of the recording [self creatSetting] } - (void)creatControl { self.playerButton = [UIButton buttonWithType:UIButtonTypeCustom] [self.playerButton setBackgroundColor:[UIColor colorWithRed:arc4random() % 255 / 255. green:arc4random() % 255 / 255. blue:arc4random() % 255 / 255. alpha:.6]] [self.playerButton setFrame:CGRectMake(0, 0, 100, 40)] [self.playerButton setCenter:CGPointMake(self.view.frame.size.width / 2, 260)] [self.playerButton setTitleColor:[UIColor colorWithRed:arc4random() % 225 / 255. green:arc4random() % 225 / 255. blue:arc4random() % 225 / 255. alpha:1] forState:UIControlStateNormal] [self.playerButton setTitle:@'play sound effect' forState:UIControlStateNormal] [self.playerButton addTarget:self action:@selector(player:) forControlEvents:UIControlEventTouchUpInside] [self.view addSubview:self.playerButton] self.recorderButton = [UIButton buttonWithType:UIButtonTypeCustom] [self.recorderButton setBackgroundColor:[UIColor colorWithRed:arc4random() % 255 / 255. green:arc4random() % 255 / 255. blue:arc4random() % 255 / 255. alpha:.6]] [self.recorderButton setTitle:@'Press and hold the recording' forState:UIControlStateNormal] [self.recorderButton setTitle: @'release end' forState:UIControlStateHighlighted] [self.recorderButton setTitleColor:[UIColor colorWithRed:arc4random() % 225 / 255. green:arc4random() % 225 / 255. blue:arc4random() % 225 / 255. alpha:1] forState:UIControlStateNormal] [self.recorderButton setFrame:CGRectMake(0, 0, 100, 40)] [self.recorderButton setCenter:CGPointMake(self.view.frame.size.width / 2, 360)] //press [self.recorderButton addTarget:self action:@selector(recorderButton:) forControlEvents:UIControlEventTouchDown] //release [self.recorderButton addTarget:self action:@selector(handleStop:) forControlEvents:UIControlEventTouchUpInside] [self.view addSubview:self.recorderButton] self.avAudionButton = [UIButton buttonWithType:UIButtonTypeCustom] [self.avAudionButton setBackgroundColor:[UIColor colorWithRed:arc4random() % 255 / 255. green:arc4random() % 255 / 255. blue:arc4random() % 255 / 255. alpha:.6]] [self.avAudionButton setFrame:CGRectMake(0, 0, 100, 40)] [self.avAudionButton setCenter:CGPointMake(self.view.frame.size.width / 2, 460)] [self.avAudionButton setTitleColor:[UIColor colorWithRed:arc4random() % 225 / 255. green:arc4random() % 225 / 255. blue:arc4random() % 225 / 255. alpha:1] forState:UIControlStateNormal] [self.avAudionButton setTitle: @'Play local' forState:UIControlStateNormal] [self.avAudionButton addTarget:self action:@selector(avAudionButton:) forControlEvents:UIControlEventTouchUpInside] [self.view addSubview:self.avAudionButton] self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 100, 30, 60)] [self.imageView setImage:[UIImage imageNamed:@'RecordingBkg']] [self.view addSubview:self.imageView] //Volume image array self.arrayImage = @[@'RecordingSignal001',@'RecordingSignal002',@'RecordingSignal003', @'RecordingSignal004', @'RecordingSignal005',@'RecordingSignal006', @'RecordingSignal007',@'RecordingSignal008'] self.imageViewSound = [[UIImageView alloc] initWithFrame:CGRectMake(60, 100, 20, 60)] [self.view addSubview:self.imageViewSound] } - (void)creatSetting { self.recordSetting = [[NSMutableDictionary alloc]init] / / Set the recording format AVFormatIDKey == kAudioFormatLinearPCM [self.recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey] / / Set the recording rate (Hz) such as: AVSampleRateKey == 8000 / 44100 / 96000 (affects the quality of the audio) [self.recordSetting setValue:[NSNumber numberWithFloat:44100] forKey:AVSampleRateKey] //Number of recording channels 1 or 2 [self.recordSetting setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey] / / linear sampling digits 8, 16, 24, 32 [self.recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey] //The quality of the recording [self.recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey] } #pragma mark - Play sound effects - (void)player:(UIButton *)button { //1. Get the full path of the sound file NSString *str = [[NSBundle mainBundle] pathForResource:@'4' ofType:@'wav'] NSURL *url = [NSURL fileURLWithPath:str] //2. Load the sound file and create a sound ID (SoundID, one ID corresponds to one sound file) SystemSoundID soundID = 0 / / Create a sound file object AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &soundID) //3. Play sound file (with vibration) AudioServicesPlayAlertSound(soundID) // The soundCompleteCallback function executed after the completion of playback AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, soundCompleteCallback, NULL) / / Pass the ID of the sound file that needs to be destroyed to it can be destroyed // AudioServicesDisposeSystemSoundID(soundID) } #pragma mark - function executed after the completion of playback void soundCompleteCallback() { NSLog (@'play completed') } #pragma mark - press method - (void)recorderButton:(UIButton *)button { self.path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@'aa.aac'] NSLog(@'%@', self.path) self.reverb = nil NSError *error = nil self.reverb = [[AVAudioRecorder alloc] initWithURL:[NSURL URLWithString:self.path] settings:self.recordSetting error:&error] / / Turn on the volume check self.reverb.meteringEnabled = YES if ([self.reverb prepareToRecord]) { [self.reverb record] self.timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(timerClick:) userInfo:nil repeats:YES] }else{ NSLog (@'recording is not ready: %@', error) } } #pragma mark - Release method - (void)handleStop:(UIButton *)button { [self.reverb stop] self.reverb = nil //Destroy the timer [self.timer invalidate] self.timer = nil / / The image value is empty self.imageViewSound.image = [UIImage imageNamed:@''] } - (void)avAudionButton:(UIButton *)button { self.player = nil / / Create a play object self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:self.path] error:nil] if ([self.player prepareToPlay]) { [self.player play] }else{ NSLog (@'player is not ready') } } #pragma mark - Timer method - (void)timerClick:(NSTimer *)timer { / / Update the score [self.reverb updateMeters] //call to refresh meter values to refresh the average and peak power, this count is measured in logarithmic scale, -160 means completely quiet, 0 means maximum input value // Get the decibel value of the specified channel: const double ALPHA = 0.05 double peakPowerForChannel = pow(10, (0.05 * [self.reverb peakPowerForChannel:0])) self.lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * self.lowPassResults if (self.lowPassResults>=0.8) { self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:7]] }else if(self.lowPassResults>=0.7){ self.imageViewSound.image = [UIImage imageNamed: [self.arrayImage objectAtIndex:6]] }else if(self.lowPassResults>=0.6){ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:5]] }else if(self.lowPassResults>=0.5){ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:4]] }else if(self.lowPassResults>=0.4){ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:3]] }else if(self.lowPassResults>=0.3){ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:2]] }else if(self.lowPassResults>=0.2){ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:1]] }else if(self.lowPassResults>=0.1){ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:0]] }else{ self.imageViewSound.image = [UIImage imageNamed:[self.arrayImage objectAtIndex:0]] } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning] // Dispose of any resources that can be recreated. } @end