LoginSignup
71

More than 5 years have passed since last update.

iOSで特定の周波数の音を鳴らす方法

Last updated at Posted at 2014-01-28

指定した周波数の音を鳴らすためのコードです。
ご参考までに。
AudioToolBox.frameworkを追加する必要があります。

ViewController.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>

@interface ViewController : UIViewController{
    AudioUnit aU;
    UInt32 bitRate;
}

@property (nonatomic) double phase;
@property (nonatomic) Float64 sampleRate;
@property (nonatomic) Float64 frequency;

static OSStatus renderer(void *inRef,
                         AudioUnitRenderActionFlags *ioActionFlags,
                         const AudioTimeStamp* inTimeStamp,
                         UInt32 inBusNumber,
                         UInt32 inNumberFrames,
                         AudioBufferList *ioData);

@end

ViewController.m
-(void)playSound{

    //Sampling rate
    _sampleRate = 44100.0f;

    //Bit rate
    bitRate = 8;  // 8bit

    //周波数(音程)
    _frequency = 261.62;

    //AudioComponentDescription
    AudioComponentDescription aCD;
    aCD.componentType = kAudioUnitType_Output;
    aCD.componentSubType = kAudioUnitSubType_RemoteIO;
    aCD.componentManufacturer = kAudioUnitManufacturer_Apple;
    aCD.componentFlags = 0;
    aCD.componentFlagsMask = 0;

    //AudioComponent
    AudioComponent aC = AudioComponentFindNext(NULL, &aCD);
    AudioComponentInstanceNew(aC, &aU);
    AudioUnitInitialize(aU);

    //コールバック
    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = renderer;
    callbackStruct.inputProcRefCon = (__bridge void*)self;
    AudioUnitSetProperty(aU,
                         kAudioUnitProperty_SetRenderCallback,
                         kAudioUnitScope_Input,
                         0,
                         &callbackStruct,
                         sizeof(AURenderCallbackStruct));

    //AudioStreamBasicDescription
    AudioStreamBasicDescription aSBD;
    aSBD.mSampleRate = _sampleRate;
    aSBD.mFormatID = kAudioFormatLinearPCM;
    aSBD.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
    aSBD.mChannelsPerFrame = 2;
    aSBD.mBytesPerPacket = sizeof(AudioUnitSampleType);
    aSBD.mBytesPerFrame = sizeof(AudioUnitSampleType);
    aSBD.mFramesPerPacket = 1;
    aSBD.mBitsPerChannel = bitRate * sizeof(AudioUnitSampleType);
    aSBD.mReserved = 0;

    //AudioUnit
    AudioUnitSetProperty(aU,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input,
                         0,
                         &aSBD,
                         sizeof(aSBD));

    //再生
    AudioOutputUnitStart(aU);

}

static OSStatus renderer(void *inRef,
                         AudioUnitRenderActionFlags *ioActionFlags,
                         const AudioTimeStamp* inTimeStamp,
                         UInt32 inBusNumber,
                         UInt32 inNumberFrames,
                         AudioBufferList *ioData) {

    //キャスト
    ViewController* def = (__bridge ViewController*)inRef;

    //サイン波
    float freq = def.frequency*2.0*M_PI/def.sampleRate;

    //値を書き込むポインタ
    AudioUnitSampleType *outL = ioData->mBuffers[0].mData;
    AudioUnitSampleType *outR = ioData->mBuffers[1].mData;

    for (int i = 0; i < inNumberFrames; i++) {
        // 周波数を計算
        float wave = sin(def.phase);
        AudioUnitSampleType sample = wave * (1 << kAudioUnitSampleFractionBits);
        *outL++ = sample;
        *outR++ = sample;
        def.phase += freq;
    }

    return noErr;

};

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71