HITONE開発日誌-02.〜AudioQueueでサイン波の出力〜

HITONEではオーディオの出力に、AudioQueueを使用しています。(AudioToolBox/AudioQueue)

オーディオデバイスに送る波形を自前で作れるので、後々拡張しやすいだろうと思いまして。

今後も音を扱う作品を作っていくつもりですのでね。

さて、HITONEの音源はサイン波です。

今回はAudioQueueのコールバックを使ってスピーカからサイン波を出力してみます。

※iPhone/iPadでの開発ですが、Objective-CではなくC++を使っています。

Objective-C++の話は、どこかでちょこっと触れるかも。

NIAudioRenderer.h

#ifndef NI_AUDIO_RENDERER_H
#define NI_AUDIO_RENDERER_H

#include <AudioToolbox/AudioQueue.h>

#include “NIDef.h”
#include “NIAudioDef.h”

#define NUM_BUFFERS 3

typedef struct AQCallbackStruct {
AudioQueueRef queue;
NIUint32 frameCount;
AudioQueueBufferRef mBuffers[NUM_BUFFERS];
AudioStreamBasicDescription mDataFormat;
} AQCallbackStruct;

class NIAudioRenderer {
public:
static void Init();
static void Term();

private:
static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB);

private:
static AQCallbackStruct _in;
static AudioQueueRef _queue;
static NIUint32 _sampleIndex;
};

#endif // AUDIO_RENDERER_H

/* EOF */

NIAudioRenderer.cpp

#include <math.h>
#include “NIAudioRenderer.h”

AQCallbackStruct NIAudioRenderer::_in;
AudioQueueRef NIAudioRenderer::_queue;

void NIAudioRenderer::AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB)
{
NIFloat floatVal;
NISint16 sampleValue; // -32767 bis +32767

AQCallbackStruct *inData = (AQCallbackStruct *)in;
NISint16 *coreAudioBuffer = (NISint16*) outQB->mAudioData;

if (inData->frameCount > 0) {
outQB->mAudioDataByteSize = 4*inData->frameCount;

for(int i=0; iframeCount*2; i=i+2) {
floatVal = sin(((NIFloat)_sampleIndex * 2 * M_PI * 440) / NI_AUDIO_SAMPLE_RATE);
sampleValue = (NISint16)(floatVal * 32767.0f);
coreAudioBuffer[i] = sampleValue;
coreAudioBuffer[i+1] = sampleValue;
_sampleIndex++;
}
AudioQueueEnqueueBuffer(inQ, outQB, 0, NULL);
} else {
AudioQueueStop(inData->queue, false);
}
}

void NIAudioRenderer::Init()
{
_in.mDataFormat.mSampleRate = NI_AUDIO_SAMPLE_RATE;
_in.mDataFormat.mFormatID = kAudioFormatLinearPCM;
_in.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
_in.mDataFormat.mBytesPerPacket = 4;
_in.mDataFormat.mFramesPerPacket = 1;
_in.mDataFormat.mBytesPerFrame = 4;
_in.mDataFormat.mChannelsPerFrame = 2;
_in.mDataFormat.mBitsPerChannel = 16;
_in.frameCount = 1024;

_sampleIndex = 0;

AudioQueueNewOutput(&_in.mDataFormat, AQBufferCallback, &_in, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &_in.queue);

UInt32 bufferBytes = _in.frameCount * _in.mDataFormat.mBytesPerFrame;

for (int i=0; i< NUM_BUFFERS; i++) {
AudioQueueAllocateBuffer(_in.queue, bufferBytes, &_in.mBuffers[i]);
AQBufferCallback (&_in, _in.queue, _in.mBuffers[i]);
}
AudioQueueSetParameter(_in.queue, kAudioQueueParam_Volume, 1.0);
AudioQueueStart(_in.queue, NULL);
_queue = _in.queue;
}

void NIAudioRenderer::Term()
{
AudioQueueStop(_queue,true);
AudioQueueDispose(_queue, true);
}
/* EOF */

ちなみに、
NIAudioDef.hとNIDef.hには
NI_AUDIO_SAMPLE_RATE
NIUint32
NISint16
NIFloat
などが定義してあります。
使う際は、ご自分の環境に合わせて定義してください。

“NI”っていうのは、あれです、自分の開発用ライブラリの名前ですね。

気にしないでOKです。

で、使うところで

#include “NIAudioRenderer.h” して

NIAudioRenderer::Init(); すれば440Hzのサイン波が出力される、はず。

終了時にNIAudiorenderer::Term(); するのをお忘れなく。

参考にしたサイト
CSPhone Project -サイン波の出力-

HITONE過去記事
01-導入-

次回はサイン波を複数鳴らしてみます。

HITONE開発日誌-01.〜導入〜

お久しぶりに書きます。

ちょっとiPhone App.の開発から離れてたんですが、ちょっときっかけがあって再開しました。

前に途中まで作っていたTiLoopは少し置いておいて、今はHITONEというアプリを作っています。

もともとは大学の卒研で、Macで(Java+Processing+Max/MSP(OpenSoundControl))動くものを作ったんですが、

そもそもタッチスクリーンで動かしてなんぼなものなので、iPhone/iPad用にリメイクしてます。

(ソース見ながら移植も考えたんですが、思い出すのも嫌になるくらい汚いコーディングをしていたのでイチから書き直してます。。。いやーおはずかしい)

卒研のときのがこれで

HITONEHITONE

現在製作中のはこんな感じになってます。

これから数回に渡って、HITONEの制作状況を記事にしていこうと思ってます。

今回、サイン波を出力するのにAudioQueueを使用していますのでまずはそこの話からですかね。

日誌と書きつつ毎日更新は出来ないと思いますが(だって書くことがなくなってしまう)

乞うご期待。

春にはリリースしたいな!

Apple Mail.app + i.softbank.jp problem

i.softbank.jpのアカウントを
Apple Mail.appからIMAPで利用しているんですが
Mail.appからのメール送信に不具合があるみたいなんですよ。

メールを作成して送信すると送信の音は鳴るし、
返信だった場合は受信メールに返信マークも付くんですが
送信したはずのメールが送信済みメールボックスにないんです。

しかも質の悪いことにこの不具合、再現性がないんですよ。
試しに自分宛に何通か送ってみたんですが
ちゃんと受信できるし送信済みボックスにも追加されるし
なんなんでしょ。
届いてるかもしれないメールを何通も送るわけにもいかないし。

ここ何ヶ月かちょこちょここういうことがあるので、
場合によって送信し直したり、送れてなくてもいいやってほっといたりしているので
僕から同じようなメールが複数届いたとか
僕からまったく返信がないとか
そういうときはこういう事情ですので許して下さい。
決して返信をせがんでいるわけでも
無視してるわけでもありません・・・

i.softbank,jpのサーバが悪いのか
Mail.appが悪いのか
はたまた送信先によってなんか変わってるのか・・・

検索しても何もわからなかったので
暇なときにアップルのサポートにでも電話してみますが
何か知ってる方がいたら教えて下さい。
Thunderbirdに乗り換えようかと思ったんですが
移行が面倒で硬直しております。

Mac OS X 10.5.6
Mail.app 3.5

iPhone for everybody キャンペーン

最近僕の周りでもにわかに話題になってますが、
今 iPhone を新規契約すると
iPhone のパケット定額料金の上限が安くなって、
2年契約の場合の月々の割引料金が大きくなるみたいです。
8GBモデルなら実質0円だそうな。(16GBモデルは480円×24ヶ月)

で、既存ユーザの僕はどうなるのよ、と思っていたのですが
どうもこういうことになるみたいです。
新モデルが出るかもしれないことを含めて
損得をちょっと計算してみようかね・・・

「iPhone実質0円」への3つの疑問

iCalでのCalDavアカウントの設定(Googleカレンダーとの同期)

普段、iCalでスケジュールを管理していて、iTunes経由でiPhoneと同期させていたのだが

先日、GoogleカレンダーがCalDAVに対応したとの話を聞き、iCalと同期させて使い始めた。

下記リンク先、参考にさせて頂きました。

「Google Calendar が CalDav をサポート — iCal/iPhone との連携がよりスマートに」

 

手順は以下。

1. iCalの「環境設定」->「アカウント」から「+」ボタンでアカウントを追加

説明:カレンダーの名前

ユーザ名:Gmailアカウントのユーザ名(@gmail.comを含む)

パスワード:Gmailアカウントのパスワード

アカウントのURL:https://www.google.com/calendar/dav/「カレンダーID」/user

(カレンダーID:Googleカレンダーの「マイカレンダー」->「設定」から同期したいカレンダーを選び、「カレンダーのアドレス」の欄を参照)

 

以上で設定は完了。なんて簡単なんだ。カレンダーの数だけ操作が必要なので少し手間はかかるけど、快適です。

 

しかし、かねてよりGoogleカレンダーを使っていた人はこれで良いけれど、iCalを使っていた場合には不便なことが。

CalDAVアカウントを設定すると新しくカレンダーが作成された形になるので、今まで使っていた予定を移動させなければいけません。

僕はiCalでカレンダーごとにひとつずつ書き出してGoogleカレンダーにインポートする、という形を取りました。

少々面倒でしたが、他に方法が見当たらなかったもので。

そして、今まで使っていたiCalのカレンダーは非表示に。(削除でも良いんでしょうけど)

これで一応解決してますが、もっとうまいやり方があれば教えて下さい。

 

もうひとつ、今までiCalではカレンダー間の移動が出来ていたんですが、(予定の編集画面で「カレンダー」を選択あるいは目的のカレンダーにドラッグアンドドロップ)

今回の方法ではカレンダー1つにつきアカウントを1つ作っているので、

予定のアカウントをまたいでの移動が出来ないことでこの作業が出来なくなってしまっています。

予定を作成するときにアカウントをちゃんと選んでからじゃないと入力し直すはめになっちゃいます。

どうにかなる方法をご存知の方、教えて下さい。

 

 

普段はiCalとiPhoneを同期しています。

今回はiCalとGoogleカレンダーの同期をやりましたので、次回はGoogleカレンダーとiPhoneの同期をやります。

これで、どこで編集してもどこへでも反映されるようになるはず!

My first iPhone App. is almost ready.

TiLoop on iPhone
TiLoopのゲームプレイ部分のシステムがほぼ出来た。

しかしやっぱり実際に作るとタスクが増えてくるなー。
(済)画面に画像を表示
(済)タッチで動かせるようにする(スライド、回転)
(済)グリッドを生成
(済)グリッド内で動くようにする
(済)グリッドにタイルを敷き詰め、移動を制限
(済)タイルを4分割
(済)Next を表示
(済)ループを検出

あとは

・スコア、タイマーあたりを作る
・設定画面を作る

だけのはずだったんだけど、

・パーツに色以外のキャラクターを持たせる
・音のことすっかり忘れてた
・消去時のエフェクト(ビジュアル)
・振ってシャッフル
・乱数の生成方法
・iPhone に最適化したスコアランキングサイト
・サイトへスコアをアップする方法
・スプラッシュ画面

増えたなー。終わるかな・・・

とりあえずアップしてあとはアップデート、ってのも、ねぇ。

 

コーディング的に参考に出来そうなところはまた後日アップします。