計算で効果音を作る2(Lazarusで直接試したい人)

記事
IT・テクノロジー
準備
お付き合いいただく前に準備してほしいこと。
まずはLazalusのインストール です
IDEは日本語に設定します 
 [Tools]-[Options]「IDE Options」窓でEmviroment-General 右上のLanguage をJapanese[Ja]でOKボタンでLazalus再起動
必要な追加すべきパッケージはACSです
インストールされてるパッケージに[laz_acs 3.03] [laz_acs_lib 3.03]がある状態が必要です
ACSstreamIn_ACS.jpg

IDE[パッケージ(c)]に[Online Package Manager]が無ければ
 IDE[パッケージ(c)]-[パッケージをインストールもしくはアンインストール]よりOnline Package Managerインストール
IDE[パッケージ(c)]-[Online Package Manager]
便利 jcfidelazarus をパッケージに追加しておけば"Ctr+D"で全行の整形をDelForExのようにしてくれます。IDEオプションにJCF整形設定があり細かな設定も可能です
ACSstreamIn_pkg.jpg

ダウンロードしたacsパッケージは C:\lazarusではなくC:\Users\自分の場所\AppData\Local\lazarus\onlinepackagemanager\packages にあります。ここに説明も demosフォルダにサンプルもあり ".lpi" をクリックすればLazarusが開きますからお試し下さい。
DirectX系のソースも入ってるようですが、DirectSound.pas等が入ってないようでコンパイルはできませんでした。

さて問題は計算で音を出したい場合です。TAcsCustomInput継承のもので使えそうなのは 
    AcsMemoryIn
    AcsStreamIn
あるいは TAcsCustomInput を継承して自分で作るかになります。
継承して自分で作るのはある程度動作したので後で公開するとして、この2つについて

AcsMemoryInはOnBufferDoneでデーター作ってやるのでしょうが、やってみるとどうすれば良いのか分からず断念。

AcsStreamInを使ってLazarusのACSで計算音を作る8step


●1.プロジェクト(P)->新規プロジェクト アプリケーションを選び[OK]
●2.Audio I/O タブから TAcsStreamIn(右から3つめ)をクリック後 Form1をクリック
●3,Audio I/O タブから TAcsAudioOut1(左から2つめ)をクリック後 Form1をクリック
ACSstreamIn_23.jpg

●4.Form1の何もない所をダブルクリック 以下のコピペ
  {copyするのは begin~end;の中の3行です}

procedure TForm1.FormCreate(Sender: TObject);
begin
  AcsStreamIn1.InBitsPerSample := 16;
  AcsStreamIn1.Stream := TMySnd.Create(AcsStreamIn1);
  AcsAudioOut1.Input := AcsStreamIn1;
end;

●5.上記FormCreateの上にカーソルを出して以下をコピペ
type
  TMySnd = class(TStream)
  protected
    FPosition: Int64;
    AcsStreamIn: TAcsStreamIn;
    function GetPosition: Int64; override;
  public
    constructor Create(const Parent: TObject);
    function Read(var Buffer; Count: Longint): Longint; override;
  end;

constructor TMySnd.Create(const Parent: TObject);
begin
  AcsStreamIn := Parent as TAcsStreamIn;
end;

function TMySnd.Read(var Buffer; Count: Longint): Longint;
var
  i, sz: Longint;
  D16: array[0..9999] of Int16 absolute Buffer;//Bufferを無理やり配列D16に見せるおまじない
begin
  with AcsStreamIn do begin
    sz := ((Count * 8) div InBitsPerSample) div InChannels; //出力すべき最大のサンプル数
    if InBitsPerSample <> 16 then raise Exception.Create('8bit未対応');
    if InChannels <> 1 then raise Exception.Create('ステレオ未対応');
  end;

  for i := 0 to sz - 1 do begin//お試しで440Hzサイン波を出しています
    D16[i] := round($7f00 * sin(PI() * 440.0 / AcsStreamIn.InSampleRate * FPosition));
    Inc(FPosition, 2);
     end;

  with AcsStreamIn do
    Result := (sz * InBitsPerSample * InChannels) div 8; //奇数の場合の為
end;

function TMySnd.GetPosition: Int64;
begin
  Result := FPosition;
end;
ACSstreamIn_1.jpg

●6.Standard タブから TButton をクリック後 Form1をクリック
●7.そのButton1をダブルクリックして以下のコピペ
  {copyするのは begin~end;の中の10行です}
procedure TForm1.Button1Click(Sender: TObject);
begin
with Button1 do
    if Tag = 0 then begin //Tagは自由に使える変数のようなもの
      Tag := 1;
      Caption := 'STOP';//動作中STOP表示 押せば止まるという意味
      AcsAudioOut1.Run();//このメソッドでReadが何度かされて音が出始めます
    end else begin
      Tag := 0;
      Caption := 'サイン波開始';
      AcsAudioOut1.Stop();
    end;
end; 
●8. F9で実行 問題なければ[Bottun1]を押せば音が出て再度押せば音が止まります
やってる内容はTStreamの継承クラスReadで16bitの配列に出力してるだけです。GetPositionメソッドも必要になるので結構面倒に見えますね。イベント処理で書けたら良いのに。


 記述途中です 追加内容によっては一部が有料になるかもしれません。

関連ブログ
を購入された方が添付ソースをビルドしたい要求があるかもしれないと、Lazarusの設定について先に公開しました

サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す ココナラコンテンツマーケット ノウハウ記事・テンプレート・デザイン素材はこちら