Tiny MML
Posted feedbacks - Objective-C
Mac OSX 10.4.10(Intel)で動作確認しています。Objective-CというよりAudio Unitの使い方ですね。 永野さんのページを参考にさせていただきました。
see: My Codex Leicester (Monalisa-au.org)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | //コンパイルオプション:-std=gnu99 -fobjc-exceptions
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Audiounit/AudioUnit.h>
OSStatus callbackProc( void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber,
UInt32 inNumberFrames, AudioBufferList* ioData ) {
static const char notes[] = "cdefedcrefgagfercrcrcrcrcdefedcr"; //かえるの歌
static const unsigned int length = sizeof notes - 1; //音符の数
static const float scale[] = { 440, 495, 264, 297, 330, 352, 396 }; //純正律音階
static const float samplingRate = 44100;
static unsigned int tempo = 160; //テンポ:八分音符/分
static unsigned int consumedFrames = 0; //現在の音符の発音済みフレーム数。1分間だとsamplingRate*60
static unsigned int index = 0; //音符のインデックス
static float phase = 0;
char note = notes[index];
float frequency = ( note >= 'a' && note <= 'g' ) ? scale[note - 'a'] : 0;
frequency *= 2 * M_PI / samplingRate;
float* outL = ioData->mBuffers[0].mData;
float* outR = ioData->mBuffers[1].mData;
for ( int i = 0; i < inNumberFrames; i++ ) {
float wave = sin( phase );
*outL++ = wave;
*outR++ = wave;
phase += frequency;
}
consumedFrames += inNumberFrames;
//規定の時間が過ぎたら次の音符へ
if ( consumedFrames >= samplingRate * 60 / tempo ) {
consumedFrames = 0;
//曲を最後まで演奏したら終了
if ( ++index >= length )
[NSApp terminate:nil];
}
return noErr;
}
BOOL initAudioUnit() {
@try {
ComponentDescription description = {
kAudioUnitType_Output, kAudioUnitSubType_DefaultOutput,
kAudioUnitManufacturer_Apple, 0, 0
};
Component component = FindNextComponent( NULL, &description );
if ( component == 0 )
@throw @"Faild to find component.";
AudioUnit audioUnit;
if ( OpenAComponent( component, &audioUnit ) != noErr )
@throw @"Faild to open component.";
AURenderCallbackStruct callbackStruct = { callbackProc, NULL };
if ( AudioUnitSetProperty( audioUnit, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &callbackStruct, sizeof callbackStruct ) != noErr )
@throw @"Faild to set property values for audio unit.";
if ( AudioUnitInitialize( audioUnit ) != noErr )
@throw @"Faild to initialize audio unit.";
if ( AudioOutputUnitStart( audioUnit ) != noErr )
@throw @"Faild to start audio unit.";
} @catch ( id error ) {
NSLog( error );
return NO;
}
return YES;
}
int main( int argc, const char** argv ) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
if ( initAudioUnit() )
[NSApp run];
[pool release];
return 0;
}
|

にしお
#3387()
Rating0/0=0.00
入力はcがド、dがレ、eがミ、fがファ、gがソ、aがラ、bがシ、rが休符とします。この8文字以外の文字は入力に含まれていないと仮定して構いません。おのおのの音符・休符は八分音符・八分休符とします。
オクターブや音の長さの変更、同時発音などの機能は不要です。
サンプル入力(カエルの歌)
[ reply ]