6

私が与えた周波数とデシベルに関連して、iPhoneでビープ音を鳴らすことについて調査しました。

私が参照したリンク:

http://developer.apple.com/library/ios/#samplecode/MusicCube/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008978

http://www.politepix.com/2010/06/18/decibel-metering-from-an-iphone-audio-unit/

http://atastypixel.com/blog/using-remoteio-audio-unit/

http://www.politepix.com/2010/06/18/decibel-metering-from-an-iphone-audio-unit/

特定の周波数の音を再生する方法とフレームワークが見つからないAudioUnitの質問

また、アプリケーションでテキスト読み上げを行うために Flite を使用しました。

fliteを使用して周波数とデシベルに関連するビープ音をiPhoneで再生することは可能ですか?

入力に従ってオーディオファイルを作成し(ピッチ、分散、速度、および指定された文字列にのみ関連する)、作成したAudioplayerを再生していることを知っています。

しかし、周波数とデシベルを設定するカスタムメソッドはありません!!!!

それで、iPhoneでそれを行う良い方法を誰かが私に提供してくれませんか。

この質問に関するヘルプをいただければ幸いです。

ありがとう

4

1 に答える 1

0

このクラスを使用すると、指定した周波数と振幅でビープ音を鳴らすことができます。AudioToolbox.frameworkのAudioQueues を使用します。これは単なるスケッチです。多くのことを改良する必要がありますが、信号を作成するメカニズムは機能します。

が表示されている場合、使用方法は非常に簡単です@interface

#import <AudioToolbox/AudioToolbox.h>
#define TONE_SAMPLERATE 44100.

@interface Tone : NSObject {
    AudioQueueRef queue;
    AudioQueueBufferRef buffer;
    BOOL rebuildBuffer;
}
@property (nonatomic, assign) NSUInteger frequency;
@property (nonatomic, assign) CGFloat dB;

- (void)play;
- (void)pause;
@end


@implementation Tone
@synthesize dB=_dB,frequency=_frequency;

void handleBuffer(void *inUserData,
                  AudioQueueRef inAQ,
                  AudioQueueBufferRef inBuffer);

#pragma mark - Initialization and deallocation -

- (id)init
{
    if ((self=[super init])) {

        _dB=0.;
        _frequency=440;
        rebuildBuffer=YES;

        // TO DO: handle AudioQueueXYZ's failures!!

        // create a descriptor containing a LPCM, mono, float format
        AudioStreamBasicDescription desc;

        desc.mSampleRate=TONE_SAMPLERATE;
        desc.mFormatID=kAudioFormatLinearPCM;
        desc.mFormatFlags=kLinearPCMFormatFlagIsFloat;
        desc.mBytesPerPacket=sizeof(float);
        desc.mFramesPerPacket=1;
        desc.mBytesPerFrame=sizeof(float);
        desc.mChannelsPerFrame=1;
        desc.mBitsPerChannel=8*sizeof(float);

        // create a new queue
        AudioQueueNewOutput(&desc,
                            &handleBuffer,
                            self,
                            CFRunLoopGetCurrent(),
                            kCFRunLoopCommonModes,
                            0,
                            &queue);

        // and its buffer, ready to hold 1" of data
        AudioQueueAllocateBuffer(queue,
                                 sizeof(float)*TONE_SAMPLERATE,
                                 &buffer);

        // create the buffer and enqueue it
        handleBuffer(self, queue, buffer);

    }
    return self;
}

- (void)dealloc
{
    AudioQueueStop(queue, YES);
    AudioQueueFreeBuffer(queue, buffer);
    AudioQueueDispose(queue, YES);

    [super dealloc];
}

#pragma mark - Main function -

void handleBuffer(void *inUserData,
                AudioQueueRef inAQ,
                AudioQueueBufferRef inBuffer) {

    // this function takes care of building the buffer and enqueuing it.

    // cast inUserData type to Tone
    Tone *tone=(Tone *)inUserData;

    // check if the buffer must be rebuilt
    if (tone->rebuildBuffer) {

        // precompute some useful qtys
        float *data=inBuffer->mAudioData;
        NSUInteger max=inBuffer->mAudioDataBytesCapacity/sizeof(float);

        // multiplying the argument by 2pi changes the period of the cosine
        //  function to 1s (instead of 2pi). then we must divide by the sample
        //  rate to get TONE_SAMPLERATE samples in one period.
        CGFloat unit=2.*M_PI/TONE_SAMPLERATE;
        // this is the amplitude converted from dB to a linear scale
        CGFloat amplitude=pow(10., tone.dB*.05);

        // loop and simply set data[i] to the value of cos(...)
        for (NSUInteger i=0; i<max; ++i)
            data[i]=(float)(amplitude*cos(unit*(CGFloat)(tone.frequency*i)));

        // inform the queue that we have filled the buffer
        inBuffer->mAudioDataByteSize=sizeof(float)*max;

        // and set flag
        tone->rebuildBuffer=NO;
    }

    // reenqueue the buffer
    AudioQueueEnqueueBuffer(inAQ,
                            inBuffer,
                            0,
                            NULL);

    /* TO DO: the transition between two adjacent buffers (the same one actually)
              generates a "tick", even if the adjacent buffers represent a continuous signal.
              maybe using two buffers instead of one would fix it.
     */
}

#pragma - Properties and methods -

- (void)play
{
    // generate an AudioTimeStamp with "0" simply!
    //  (copied from FillOutAudioTimeStampWithSampleTime)

    AudioTimeStamp time;

    time.mSampleTime=0.;
    time.mRateScalar=0.;
    time.mWordClockTime=0.;
    memset(&time.mSMPTETime, 0, sizeof(SMPTETime));
    time.mFlags = kAudioTimeStampSampleTimeValid;

    // TO DO: maybe it could be useful to check AudioQueueStart's return value
    AudioQueueStart(queue, &time);
}

- (void)pause
{
    // TO DO: maybe it could be useful to check AudioQueuePause's return value
    AudioQueuePause(queue);
}

- (void)setFrequency:(NSUInteger)frequency
{
    if (_frequency!=frequency) {
        _frequency=frequency;

        // we need to update the buffer (as soon as it stops playing)
        rebuildBuffer=YES;
    }
}

- (void)setDB:(CGFloat)dB
{
    if (dB!=_dB) {
        _dB=dB;

        // we need to update the buffer (as soon as it stops playing)
        rebuildBuffer=YES;
    }
}

@end
  • このクラスは、指定された整数周波数 (振幅*cos(2pi*周波数*t) ) で振動する cos 波形を生成します。すべての作業はvoid handleBuffer(...)、リニア PCM、モノラル、float @44.1kHz フォーマットの AudioQueue を使用して行われます。信号の形状を変更するには、その線を変更するだけです。たとえば、次のコードは方形波を生成します。

    float x = fmodf(unit*(CGFloat)(tone.frequency*i), 2 * M_PI);
    data[i] = amplitude * (x > M_PI ? -1.0 : 1.0);
    
  • 浮動小数点周波数の場合、オーディオ データの 1 秒間に必ずしも整数の振動数があるとは限らないことを考慮する必要があります。そのため、表現される信号は 2 つのバッファ間のジャンクションで不連続になり、奇妙な「ティック」を生成します。たとえば、ジャンクションが信号期間の終わりになるようにサンプルを少なく設定できます。

  • Paul R が指摘したように、最初にハードウェアを調整して、実装で設定した値とデバイスによって生成されるサウンドとの間の信頼できる変換を取得する必要があります。実際には、このコードで生成される浮動小数点サンプルの範囲は -1 から 1 であるため、振幅値を dB ( 20*log_10(amplitude) ) に変換しただけです。
  • 実装のその他の詳細と「既知の制限」(これらすべての「TO DO」) については、コメントを参照してください。使用される関数は、Apple のリファレンスで十分に文書化されています。
于 2012-11-11T02:13:52.457 に答える