开发者

Generating Morse code style tones in objective-c

I have a class that will let me play a tone using audio units, what i would like to be able to do is have the class play morse code style when i send the class a phrase or letter.

How would i go about this? I'm hoping someone can point me in the right direction. i have included the tone generator .h and .m files below

    //
//  Singer.h
//  musicules开发者_JAVA技巧dev
//
//  Created by Dylan on 2/20/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

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



@interface Singer : NSObject {


    AudioComponentInstance audioUnit;

}


-(void)initAudio; // put this in init?


-(void)start;
-(void)stop;
-(IBAction)turnOnSound:(id)sender;

@end


//
//  Singer.m
//  musiculesdev
//
//  Created by Dylan on 2/20/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import <AudioUnit/AudioUnit.h>
#import <math.h>

#import "Singer.h"

#define kOutputBus 0
#define kSampleRate 44100
//44100.0f
#define kWaveform (M_PI * 2.0f / kSampleRate)


@implementation Singer


OSStatus playbackCallback(void *inRefCon,
                          AudioUnitRenderActionFlags *ioActionFlags,
                          const AudioTimeStamp *inTimeStamp,
                          UInt32 inBusNumber, 
                          UInt32 inNumberFrames,
                          AudioBufferList *ioData) {    

    //Singer *me = (Singer *)inRefCon;

    static int phase = 0;

    for(UInt32 i = 0; i < ioData->mNumberBuffers; i++) {

        int samples = ioData->mBuffers[i].mDataByteSize / sizeof(SInt16);

        SInt16 values[samples];

        float waves;

        for(int j = 0; j < samples; j++) {


            waves = 0;


            waves += sin(kWaveform * 261.63f * phase);
            waves += sin(kWaveform * 120.0f * phase);
            waves += sin(kWaveform * 1760.3f * phase);
            waves += sin(kWaveform * 880.0f * phase);            

            waves *= 32500 / 4; // <--------- make sure to divide by how many waves you're stacking

            values[j] = (SInt16)waves;
            values[j] += values[j]<<16;

            phase++;

        }

        memcpy(ioData->mBuffers[i].mData, values, samples * sizeof(SInt16));

    }


    return noErr;

}

-(IBAction)turnOnSound:(id)sender {
    Singer *singer = [[Singer alloc] init];

    [singer start];
}


-(id)init {
    NSLog(@"In the singer init!!");
    if(self = [super init]) {

        [self initAudio];

    }

    return self;

}

-(void)initAudio {

    OSStatus status;

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

    AudioComponent outputComponent = AudioComponentFindNext(NULL, &desc);

    status = AudioComponentInstanceNew(outputComponent, &audioUnit);

    UInt32 flag = 1;
    status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag));

    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate = kSampleRate;
    audioFormat.mFormatID = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket = 1;
    audioFormat.mChannelsPerFrame = 1;
    audioFormat.mBitsPerChannel = 16;
    audioFormat.mBytesPerPacket = 2;
    audioFormat.mBytesPerFrame = 2;

    status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &audioFormat, sizeof(audioFormat));

    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = playbackCallback;
    callbackStruct.inputProcRefCon = self;

    status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &callbackStruct, sizeof(callbackStruct));

    status = AudioUnitInitialize(audioUnit);

}

-(void)start {

    OSStatus status;

    status = AudioOutputUnitStart(audioUnit);

}

-(void)stop {

    OSStatus status;

    status = AudioOutputUnitStop(audioUnit);

}

-(void)dealloc {

    AudioUnitUninitialize(audioUnit);

    [super dealloc];

}

@end


You need to be able to generate tones of a specific duration, separated by silences of a specific duration. So long as you have these two building blocks you can send morse code:

dot = 1 unit
dash = 3 units
space between dots/dashes within a letter = 1 unit
space between letters = 3 units
space between words = 5 units

The length of unit determines the overall speed of the morse code. Start with e.g. 50 ms.

The tone should just be a pure sine wave at an appropriate frequency, e.g. 400 Hz. The silence can just be an alternate buffer containing all zeroes. That way you can "play" both the tone and the silence using the same API, without worrying about timing/synchronisation, etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜