SiioLaboratory

iPhoneのアプリケーション開発を行うための、ごくごく簡単なメモです。 iPhoneアプリを開発するための How2iPhoneProgramming をも参考にしてください。

iPhoneから正弦波を出す方法

Audio Toolbox .framework を使う

xcodeで、Audio Toolbox フレームワークを設定しておく。

http://gyazo.com/61baab77ba29820c376c9106c0d67c16.png

次に、以下のクラスを作っておく。

Sound Player .h

//
//  SoundPlayer.h
//
//  Created by SIIO Itiro on 11/04/17.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h> 

@interface SoundPlayer : NSObject {
	AudioQueueRef queueRef;
}


-(id)init;
-(void)start; 
-(void)pause; 
-(void)stop; 

@end

Sound Player .m

//
//  SoundPlayer.m
//
//  Created by SIIO Itiro on 11/04/17.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "SoundPlayer.h"


#define SAMPLERATE 44100.0f
#define FL ((2.0f * 3.14159f) / SAMPLERATE) 
#define FR ((2.0f * 3.14159f) / SAMPLERATE) 
#define FRAMECOUNT 1024
#define NUM_BUFFERS 3



@implementation SoundPlayer

static void aqCallBack(void *in, AudioQueueRef q, AudioQueueBufferRef qb) { 
	
	static int phaseL = 0; 
	static int phaseR = 0; 
	
	short *sinBuffer = (short *)qb->mAudioData; 
	
    float sampleL = 0.0f; 
    float sampleR = 0.0f; 
	
	float amplitude = 1.0f, pitch=100.0f;
	
	qb->mAudioDataByteSize = 4 * FRAMECOUNT; 
	// 1 frame per packet, two shorts per frame = 4 * frames 
	for(int i = 0; i < ( FRAMECOUNT * 2 ) ; i+=2) {
		sampleL = (amplitude * sin(pitch * FL * (float)phaseL));
		sampleR = (amplitude * sin(pitch * FR * (float)phaseR));
	
		short sampleIL = (int)(sampleL * 32767.0f); 
		short sampleIR = (int)(sampleR * 32767.0f); 
		sinBuffer[i] = sampleIL; 
		sinBuffer[i+1] = sampleIR; 
		phaseL++; 
		phaseR++; 
	}//end for
	AudioQueueEnqueueBuffer(q, qb, 0, NULL); 
	
} 
	
	
-(id)init { 
	AudioStreamBasicDescription dataFormat;
    AudioQueueBufferRef buffers[NUM_BUFFERS]; 
	
	self = [super init];
	
	dataFormat.mSampleRate = SAMPLERATE; 
	dataFormat.mFormatID = kAudioFormatLinearPCM; 
	dataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
	dataFormat.mBytesPerPacket = 4; 
	dataFormat.mFramesPerPacket = 1; 
	dataFormat.mBytesPerFrame = 4; 
	dataFormat.mChannelsPerFrame = 2; 
	dataFormat.mBitsPerChannel = 16; 

	AudioQueueNewOutput(&dataFormat, aqCallBack, self, NULL, kCFRunLoopCommonModes, 0, &queueRef); // CFRunLoopGetCurrent() 

	for(int i = 0; i < NUM_BUFFERS; i++) { 
	
		UInt32 err = 
		AudioQueueAllocateBuffer(queueRef, FRAMECOUNT * dataFormat.mBytesPerFrame, &buffers[i]); 
		if(err) { 
			NSLog(@"err:%d\n"); 
		}//end if 
	
		aqCallBack(self, queueRef, buffers[i]); //prime buffer 
	}//end for
	AudioQueueSetParameter(queueRef, kAudioQueueParam_Volume, 1.0f); 

	return self; 
	
} 
	
	
-(void)start { 
	AudioQueueStart(queueRef, NULL); 
} 

-(void)pause{
	AudioQueuePause(queueRef);
}
	
-(void)stop { 
	AudioQueueStop(queueRef, true); 
} 
			
-(void)dealloc { 
	AudioQueueDispose(queueRef, true); 
	[super dealloc]; 
} 
	

@end

使い方

どこかで

SoundPlayer *sp1;

と定義しておいて、

sp1 = [[SoundPlayer alloc] init];

としてインスタンス化する。これに対して、

[sp1 start];

とすれば100kHzの正弦波が再生される。 一方、

[sp1 pause];

とすれば、再生が停止する。最後に、どこかで、

[sp1 dealloc];

として解放しておくことを忘れずに。

参考サイト


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-11-18 (水) 20:51:48