Menghasilkan Tone Menggunakan Delphi

September 1, 2006 at 4:46 pm | Posted in Code Samples, Tutorials | 31 Comments
Tags: ,

oleh Zamrony P Juhara

Untuk membuat bunyi tone yang frekuensinya ditentukan saat runtime, kita bisa menggunakan Beep() milik Windows. Fungsi ini simple tapi sayangnya mungkin untuk beberapa kasus, tidak cocok. Contohnya suara beep yang dibangkitkan, tidak bisa disimpan di file. Problem ini sempat mengemuka di milis Delphindo. Oleh karena itu saya tulis artikelnya.

Untuk artikel kali ini, kita akan membuat aplikasi tone generator. Tone generator ini saya buat ketika terlibat dalam sebuah proyek active noise cancellation yakni sistem peredaman suara aktif dimana gelombang suara diredam menggunakan gelombang suara yang sama tapi dengan fase yang berbeda 180 derajat.


ok langsung saja ke kode. Kode berikut ini adalah deklarasi tipe-tipe yang akan kita pakai di tone generator dan beberapa deklarasi fungsi-fungsi helper. Tidak susah bukan..

{======================================
Sound type definition
=======================================
(c) 2006 zamrony p juhara
=======================================}
unit uSoundTypes;

interface

type

  TVolumeLevel = 0..127;
  TSampleRate=(sr8KHz,sr11_025KHz,sr22_05KHz,sr44_1KHz);
  TSoundChannel=(chMono,chStereo);
  TBitsPerSample=(bps8Bit,bps16Bit,bps32Bit);

function GetSampleRate(SampleRate:TSampleRate):integer;
function GetEnumSampleRate(SampleRate:integer):TSampleRate;

function GetNumChannels(ch:TSoundChannel):word;
function GetSoundChannels(nChannel:word):TSoundChannel;

function GetBitsPerSample(bits:TBitsPerSample):word;
function GetEnumBitsPerSample(bits:word):TBitsPerSample;

implementation


const SampleRates:array[sr8KHz..sr44_1KHz] of integer=
       (8000,11025,22050,44100);

     Channels:array[chMono..chStereo] of word=
     (1,2);
     BitsPerSample:array[bps8Bit..bps32Bit] of word=
     (8,16,32);

function GetSampleRate(SampleRate:TSampleRate):integer;
begin
  result:=SampleRates[SampleRate];
end;

function GetEnumSampleRate(SampleRate:integer):TSampleRate;
begin
  result:=sr8KHz;
  case sampleRate of
    8000:result:=sr8KHz;
    11025:result:=sr11_025KHz;
    22050:result:=sr22_05KHz;
    44100:result:=sr44_1KHz;
  end;
end;

function GetNumChannels(ch:TSoundChannel):word;
begin
  result:=Channels[ch];
end;

function GetSoundChannels(nChannel:word):TSoundChannel;
begin
  result:=chMono;
  case nChannel of
    1:result:=chMono;
    2:result:=chStereo;
  end;
end;

function GetBitsPerSample(bits:TBitsPerSample):word;
begin
  result:=BitsPerSample[bits];
end;

function GetEnumBitsPerSample(bits:word):TBitsPerSample;
begin
  result:=bps8Bit;
  case bits of
    8:result:=bps8Bit;
    16:result:=bps16Bit;
    32:result:=bps32Bit;
  end;
end;

end.

Berikut ini adalah inti dari aplikasi tone generator.

{======================================
Tone Generator Wrapper class
=======================================
(c) 2006 zamrony p juhara
=======================================}

unit uToneGenerator;

interface
uses classes,uSoundTypes;


type
  TBasicToneGenerator=class(TPersistent)
  private
    FStream:TMemoryStream;
    FDuration: integer;
    FSampleRate: TSampleRate;
    FVolume: TVolumeLevel;
    FChannel: TSoundChannel;
    procedure SetDuration(const Value: integer);
    procedure SetSampleRate(const Value: TSampleRate);
    procedure SetVolume(const Value: TVolumeLevel);
    procedure SetChannel(const Value: TSoundChannel);
  protected

  public
    constructor Create;virtual;
    destructor Destroy;override;
    procedure Generate;virtual;
    procedure Play;
    procedure PlaySync;
    procedure SaveToStream(Stream:TStream);
    procedure SaveToFile(const filename:string);
    procedure LoadFromStream(Stream:TStream);
    procedure LoadFromFile(const filename:string);
  published
    property SampleRate:TSampleRate read FSampleRate write SetSampleRate;
    property Duration:integer read FDuration write SetDuration;
    property Volume:TVolumeLevel read FVolume write SetVolume;
    property Channel:TSoundChannel read FChannel write SetChannel;
    property ToneStream:TMemoryStream read FStream;
  end;

  TToneGenerator=class(TBasicToneGenerator)
  private
    FFrequency: integer;
    procedure SetFrequency(const Value: integer);
  public
    constructor Create;override;
    procedure Generate;override;
  published
    property Frequency:integer read FFrequency write SetFrequency;
  end;

  TWhiteNoiseGenerator=class(TBasicToneGenerator)
  private
  public
    procedure Generate;override;
  published
  end;


{======================================
Menghasilkan tone dan menyimpannya ke stream
=======================================}
procedure GenerateToneToStream(Stream:TStream;
                     const Frequency{Hz},
                     Duration{mSec}: Integer;
                    const Volume: TVolumeLevel;
                    const nChannel:TSoundChannel;
                    const Sample_Rate:TSampleRate=sr44_1KHz);

{======================================
Menghasilkan noise dan menyimpannya ke stream
=======================================}
procedure GenerateNoiseToStream(Stream:TStream;
                    const Duration{mSec}: Integer;
                    const Volume: TVolumeLevel;
                    const nChannel:TSoundChannel;
                    const Sample_Rate:TSampleRate=sr44_1KHz);

implementation
uses windows,sysutils,MMSystem;



procedure GenerateToneToStream(Stream:TStream;
                     const Frequency{Hz},
                     Duration{mSec}: Integer;
                    const Volume: TVolumeLevel;
                    const nChannel:TSoundChannel;
                    const Sample_Rate:TSampleRate=sr44_1KHz);
var
  WaveFormatEx: TWaveFormatEx;
  i, sizeByte,TempInt, DataCount, RiffCount: integer;
  SoundValue: byte;
  // w=omega ( 2 * pi * frequency)
  //w_per_samplerate=w/samplerate
  w,w_per_samplerate: double;
  SampleRate:integer;
const
  RiffId: string = 'RIFF';
  WaveId: string = 'WAVE';
  FmtId: string = 'fmt ';
  DataId: string = 'data';
begin
  SampleRate:=GetSampleRate(Sample_Rate);
  if Frequency > (0.6 * SampleRate) then
    raise Exception.Create(Format('Sample rate %d terlalu sedikit untuk memainkan tone %dHz',
                                  [SampleRate, Frequency])
                           );

  with WaveFormatEx do
  begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := GetNumChannels(nChannel);
    nSamplesPerSec := SampleRate;
    wBitsPerSample := $0008;
    nBlockAlign := (nChannels * wBitsPerSample) div 8;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;
  {hitung panjang data sound dan panjang stream WAV yang harus dihasilkan}
  DataCount := (Duration * SampleRate) div 1000; // sound data
  TempInt := SizeOf(TWaveFormatEx);
  RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +
               TempInt + Length(DataId) + SizeOf(DWORD) + DataCount; // file data
  {tulis wave header}
  Stream.WriteBuffer(RiffId[1], 4); // 'RIFF'
  Stream.WriteBuffer(RiffCount, SizeOf(DWORD)); // file data size
  Stream.WriteBuffer(WaveId[1], Length(WaveId)); // 'WAVE'
  Stream.WriteBuffer(FmtId[1], Length(FmtId)); // 'fmt '
  Stream.WriteBuffer(TempInt, SizeOf(DWORD)); // TWaveFormat data size
  Stream.WriteBuffer(WaveFormatEx, TempInt); // WaveFormatEx record
  Stream.WriteBuffer(DataId[1], Length(DataId)); // 'data'
  Stream.WriteBuffer(DataCount, SizeOf(DWORD)); // sound data size
  sizeByte:=Sizeof(Byte);
  {hitung dan simpan tone signal ke stream}
  w := 2 * Pi * Frequency; // omega
  w_per_samplerate:=w/SampleRate;
  for i := 0 to DataCount - 1 do
  begin
    SoundValue := 127 + trunc(Volume * sin(i * w_per_SampleRate)); // wt = w * i / SampleRate
    Stream.WriteBuffer(SoundValue, SizeByte);
  end;
end;

{ TBasicToneGenerator }

constructor TBasicToneGenerator.Create;
begin
  FStream:=nil;
  FDuration:=1000;
  FSampleRate:=sr22_05KHz;
  FVolume:=127;
  FChannel:=chMono;
end;

destructor TBasicToneGenerator.Destroy;
begin
  FStream.Free;
  inherited;
end;

procedure TBasicToneGenerator.Generate;
begin
  if FStream=nil then
    FStream:=TMemoryStream.Create;
  FStream.Clear;
end;

procedure TBasicToneGenerator.LoadFromFile(const filename: string);
var afile:TFileStream;
begin
  afile:=TFileStream.Create(filename,fmOpenRead);
  try
    LoadFromStream(afile);
  finally
    afile.Free;
  end;
end;

procedure TBasicToneGenerator.LoadFromStream(Stream: TStream);
begin
  if FStream=nil then
    FStream:=TMemoryStream.Create;
  FStream.Clear;
  FStream.CopyFrom(Stream,0);
end;

procedure TBasicToneGenerator.Play;
begin
  if FStream.Size<>0 then
    PlaySound(FStream.Memory,0, SND_MEMORY or SND_ASYNC);
end;

procedure TBasicToneGenerator.PlaySync;
begin
  if FStream.Size<>0 then
    PlaySound(FStream.Memory,0, SND_MEMORY or SND_SYNC);
end;

procedure TBasicToneGenerator.SaveToFile(const filename: string);
var afile:TFileStream;
begin
  afile:=TFileStream.Create(filename,fmCreate);
  try
    SaveToStream(afile);
  finally
    afile.Free;
  end;
end;

procedure TBasicToneGenerator.SaveToStream(Stream: TStream);
begin
  Stream.Seek(0,soFromBeginning);
  Stream.CopyFrom(FStream,0);
end;


procedure TBasicToneGenerator.SetChannel(const Value: TSoundChannel);
begin
  FChannel := Value;
end;

procedure TBasicToneGenerator.SetDuration(const Value: integer);
begin
  FDuration := Value;
end;


procedure TBasicToneGenerator.SetSampleRate(const Value: TSampleRate);
begin
  FSampleRate := Value;
end;

procedure TBasicToneGenerator.SetVolume(const Value: TVolumeLevel);
begin
  FVolume := Value;
end;

{TToneGenerator}

constructor TToneGenerator.Create;
begin
  inherited Create;
  FFrequency:=1000;
end;

procedure TToneGenerator.Generate;
begin
  inherited;
  GenerateToneToStream(FStream,
                       FFrequency,
                       FDuration,
                       FVolume,
                       FChannel,
                       FSampleRate);
end;

procedure TToneGenerator.SetFrequency(const Value: integer);
begin
  FFrequency := Value;
end;

function random_negative(const value:double):double;
begin
  if random>0.5 then
    result:=-value
  else
    result:=value;
end;

procedure GenerateNoiseToStream(Stream:TStream;
                     const Duration{mSec}: Integer;
                    const Volume: TVolumeLevel;
                    const nChannel:TSoundChannel;
                    const Sample_Rate:TSampleRate=sr44_1KHz);
var
  WaveFormatEx: TWaveFormatEx;
  i, sizeByte,TempInt, DataCount, RiffCount: integer;
  SoundValue: byte;
  SampleRate:integer;
const
  RiffId: string = 'RIFF';
  WaveId: string = 'WAVE';
  FmtId: string = 'fmt ';
  DataId: string = 'data';
begin
  SampleRate:=GetSampleRate(Sample_Rate);

  with WaveFormatEx do
  begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := GetNumChannels(nChannel);
    nSamplesPerSec := SampleRate;
    wBitsPerSample := $0008;
    nBlockAlign := (nChannels * wBitsPerSample) div 8;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;
  {hitung panjang data sound dan panjang stream WAV yang harus dihasilkan}
  DataCount := (Duration * SampleRate) div 1000; // sound data
  TempInt := SizeOf(TWaveFormatEx);
  RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +
               TempInt + Length(DataId) + SizeOf(DWORD) + DataCount; // file data
  {tulis wave header}
  Stream.WriteBuffer(RiffId[1], 4); // 'RIFF'
  Stream.WriteBuffer(RiffCount, SizeOf(DWORD)); // file data size
  Stream.WriteBuffer(WaveId[1], Length(WaveId)); // 'WAVE'
  Stream.WriteBuffer(FmtId[1], Length(FmtId)); // 'fmt '
  Stream.WriteBuffer(TempInt, SizeOf(DWORD)); // TWaveFormat data size
  Stream.WriteBuffer(WaveFormatEx, TempInt); // WaveFormatEx record
  Stream.WriteBuffer(DataId[1], Length(DataId)); // 'data'
  Stream.WriteBuffer(DataCount, SizeOf(DWORD)); // sound data size
  sizeByte:=Sizeof(Byte);

  {hitung dan simpan tone signal ke stream}
  for i := 0 to DataCount - 1 do
  begin
    SoundValue := 127 + trunc(Volume * random_negative(random));
    Stream.WriteBuffer(SoundValue, SizeByte);
  end;
end;

{ TWhiteNoiseGenerator }

procedure TWhiteNoiseGenerator.Generate;
begin
  inherited;
  GenerateNoiseToStream(FStream,
                        FDuration,
                        FVolume,
                        FChannel,
                        FSampleRate);
end;


initialization
randomize;
end.


Ok mari kita bahas kode inti kelas TToneGenerator.


procedure GenerateToneToStream(Stream:TStream;
                     const Frequency{Hz},
                     Duration{mSec}: Integer;
                    const Volume: TVolumeLevel;
                    const nChannel:TSoundChannel;
                    const Sample_Rate:TSampleRate=sr44_1KHz);
var
  WaveFormatEx: TWaveFormatEx;
  i, sizeByte,TempInt, DataCount, RiffCount: integer;
  SoundValue: byte;
  // w=omega ( 2 * pi * frequency)
  //w_per_samplerate=w/samplerate
  w,w_per_samplerate: double;
  SampleRate:integer;
const
  RiffId: string = 'RIFF';
  WaveId: string = 'WAVE';
  FmtId: string = 'fmt ';
  DataId: string = 'data';
begin
  SampleRate:=GetSampleRate(Sample_Rate);
  if Frequency > (0.6 * SampleRate) then
    raise Exception.Create(Format('Sample rate %d terlalu sedikit untuk memainkan tone %dHz',
                                  [SampleRate, Frequency])
                           );

  with WaveFormatEx do
  begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := GetNumChannels(nChannel);
    nSamplesPerSec := SampleRate;
    wBitsPerSample := $0008;
    nBlockAlign := (nChannels * wBitsPerSample) div 8;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;
  {hitung panjang data sound dan panjang stream WAV yang harus dihasilkan}
  DataCount := (Duration * SampleRate) div 1000; // sound data
  TempInt := SizeOf(TWaveFormatEx);
  RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +
               TempInt + Length(DataId) + SizeOf(DWORD) + DataCount; // file data
  {tulis wave header}
  Stream.WriteBuffer(RiffId[1], 4); // 'RIFF'
  Stream.WriteBuffer(RiffCount, SizeOf(DWORD)); // file data size
  Stream.WriteBuffer(WaveId[1], Length(WaveId)); // 'WAVE'
  Stream.WriteBuffer(FmtId[1], Length(FmtId)); // 'fmt '
  Stream.WriteBuffer(TempInt, SizeOf(DWORD)); // TWaveFormat data size
  Stream.WriteBuffer(WaveFormatEx, TempInt); // WaveFormatEx record
  Stream.WriteBuffer(DataId[1], Length(DataId)); // 'data'
  Stream.WriteBuffer(DataCount, SizeOf(DWORD)); // sound data size
  sizeByte:=Sizeof(Byte);
  {hitung dan simpan tone signal ke stream}
  w := 2 * Pi * Frequency; // omega
  w_per_samplerate:=w/SampleRate;
  for i := 0 to DataCount - 1 do
  begin
    SoundValue := 127 + trunc(Volume * sin(i * w_per_SampleRate)); // wt = w * i / SampleRate
    Stream.WriteBuffer(SoundValue, SizeByte);
  end;
end;

Ok mari kita buat sebuah demo aplikasi untuk memanfaatkan kelas TToneGenerator kita. Buatlah aplikasi baru dan drag drop kontrol-kontrol seperti dibawah ini. Kemudaian lengkapi event handler button Generate dan Save seperti berikut:

form_design.gif

{======================================
Tone Generator Demo
=======================================
(c) 2006 zamrony p juhara
=======================================}
unit UfrmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls,uSoundTypes,uToneGenerator, ExtCtrls;

type
  TfrmMain = class(TForm)
    btnGenerate: TButton;
    edFrequency: TEdit;
    lblFrequency: TLabel;
    edDuration: TEdit;
    lblDuration: TLabel;
    lblHz: TLabel;
    lblMSec: TLabel;
    trckbrVolume: TTrackBar;
    lblVolume: TLabel;
    cmbxSampleRate: TComboBox;
    lblSampleRate: TLabel;
    btnSave: TButton;
    SaveDialog1: TSaveDialog;
    rdgrpChannel: TRadioGroup;
    procedure btnGenerateClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
  private
    tone:TToneGenerator;
    { Private declarations }
  public
    constructor Create(AOwner:TComponent);override;
    destructor destroy;override;
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation


{$R *.dfm}

procedure TfrmMain.btnGenerateClick(Sender: TObject);
begin
  tone.Frequency:=strToInt(edFrequency.Text);
  tone.Duration:=strToInt(edDuration.Text);
  tone.Volume:=TVolumeLevel(trckBrVolume.Position);
  tone.SampleRate:=TSampleRate(cmbxSampleRate.ItemIndex);
  if rdgrpChannel.ItemIndex=0 then
    tone.Channel:=chMono
  else
    tone.Channel:=chStereo;

  tone.Generate;
  tone.Play;
  btnSave.Enabled:=true;
end;

constructor TfrmMain.Create(AOwner: TComponent);
begin
  inherited;
  tone:=TToneGenerator.Create;
  btnSave.Enabled:=false;
end;

destructor TfrmMain.destroy;
begin
  tone.Free;
  inherited;
end;

procedure TfrmMain.btnSaveClick(Sender: TObject);
begin
  if SaveDialog1.Execute then
    tone.SaveToFile(SaveDialog1.Filename);
end;

end.

Lakukan kompilasi dan run. Jangan lupa pastikan speaker anda dalam kondisi ON. Tiap kali button Generate di klik, akan diperdengarkan bunyi tone yang frekuensinya diinputkan dari edit box.

Bunyi tone dapat disimpan sebagai file WAV untuk dimainkan dengan player lain.

Source code bisa di download di sini

31 Comments »

RSS feed for comments on this post. TrackBack URI

  1. kerenz euy,
    Mas Zamrony bisa tampilkan rumus2 yang digunakan (klo berkenan kirim ke email mat_sakuraba et yahoo.com.sg).

    saya juga pake unit beeper buatan David Taylor.
    buat TA saya, tapi nggak ngerti rumus2 nya.
    belum begitu ngerti bhs delphi, jadi blom bisa menerjemahkan unit beeper tersebut menjadi rumus2 biasa.

    makasih.

  2. Sangat membantu buanget Bozzzzz…..Thanks tipsnya…..Akhirnya delphi punya tempat sendiri…..

  3. Hallo Mas Juhara,

    OK banget. Saya ada pertanyaan mungkin untuk menghasilkan nada alat musik.
    Sekarang bagaimana untuk men-generate beberapa tone sekaligus bersamaan, seperti proses modulai amplitudo satu frekuensi sebagai carriernya dan satu frekuensi lainnya yang menumpang.

    Terma kasih sebelumnya.

    wessy

  4. Untuk mengabungkan beberapa frekuensi, caranya mudah tinggal jumlahkan saja frekuensi pertama dengan frekuensi kedua

    Hasilnya adalah tone hasil modulasi. Yang tinggal anda ubah adalah perhitungan sound value
    SIN(i*omega)

    dengan looping untuk tiap-tiap gelombang

    Sin(i*omega1)+sin(i*omega2)+sin(i*omega3)+….

    baru kemudian datanya disimpan ke stream

  5. MAS,minta bantu tentang cara menginputkan video atau image dari webcam ke borland delphi6.0 untuk dicapture,bagaimana ya…kalau boleh SC dan tampilannya.
    terimakasih

  6. kereeeeeen abis,mas ini membantua boaanget tuk TA saya

  7. dead link utk downloadnya

    • TTonegenerator is still on in my closed room? wondering why he dissapear? from Internet… ?

  8. Nama saya … Ikhsan Yuratama
    Asal : Palembang

    Saya sangat suka mendalami pemrograman Borland Delphi
    Ilmu yang saya miliki saat ini masih sangat lah dangkal khususnya dalam pemrograman Borland Delphi..

    Saat ini saya ingin membuat aplikasi client server ( jaringan ) menggunakan webcam melalui pemrograman Borland Delphi

    Jadi hasil yang dicapai adalah…
    Komputer yang terhubung dalam sebuah jaringan tersebut dapat saling berkomunikasi atau berpandangan ( tatap muka )
    Dapat saling berbicara…melalui mic..
    minimalnya..dapat saling tatap muka..

    Kesulitan saya…
    Saya tidak ada panduan untuk membuat aplikasi tersebut…
    Baik dari Buku..ataupun source code ..

    Yang saya ingin Tanya kan..
    Bagaimana membuat aplikasi tersebut.
    Adakah contoh dari aplikasi tersebut, dan boleh kah saya mempelajarinya
    Adakah buku tentang aplikasi tersebut..dan apa judul bukunya…
    Dimana saya dapat mencari nya tentang aplikasi tersebut

    Dengan segala hormat saya
    Saya..mohon solusinya…

    Di Palembang .. buku tentang Borland Delphi ini sangat lah sedikit…
    Sebelum dan sesudah nya saya ucapkan terima kasih sebesar-besarnya..

    Hormat saya

    Ikhsan Yuratama

  9. Wah artikelnya bagus sekali, saya sudah lama ingin mencoba bermain-main dengan audio di delphi.

  10. Mas saya butuh banged nich, saya ta tapi ada kesulitan saat write wav file di delphi…… kok tidak bisa kaya aslinya gimana ya…

    Read > Write Wav di delphi gimana donk…

    mohon bantuannya

  11. kalau mau write wav mono 8 bit…
    adakah…rumus untuk menulis nilai data suaranya apabila di ambil data suaranya dari array.
    yang sepengetahuan saya wav mono 8 bit itu 1 sample
    1 byte dan panjang properti data length dan numsample adalah sama panjangnya,,,
    mohon penjelasannya.
    terima kasih…

  12. khusus untuk waveformat WAVE_FORMAT_PCM, untuk menulis waveformat nBlockAlign adalah jumlah channel *jumlah bit dibagi 8. Jadi untuk mono 8 bit. blok align adalah 1*8 div 8=1
    untuk kecepatan transfer data (average bytes per second) adalah hasil kali sample rate dengan block align. Jadi bila sample rate yang diinginkan 22050 Hz maka butuh transfer data per detik 22050*1=22050 bytes.

    untuk data 8 bit, range amplitudo adalah 0 (min)-255 (max) dimana 127 adalah silence. Jika kita isi 127 semua data WAV maka ketika dimainkan yang terdengar adalah silence.
    untuk 16 bit range amplitudi min dan max adalah 0-65535, dengan 32767 ada silence.

    untuk mono, tiap data akan dimainkan pada masing-masing speaker. untuk stereo, tiap-tiap sample data terdiri atas dua data, chhanel left dan right

  13. Hebat ….
    Salut ….

    • Bon!, bien de la presence! question je crois que la question est ttonegenerator.. en fait j’ai father and sun Ttonegenerator sleeping in a dark room?!
      salut bat.eh

  14. mas q mau bt tugas mandiri.tolong bantuin dong

  15. yg mo saya tanyakan…kalo yg di sample rate itu 0.6*…diganti jadi 0.9 ato berapa terus buat membangkitkan tone dengan frek lebih dr 22000 hz kok tetep kedengeran ya? padahal suara yg bisa didengar manusi max 20khz kan ya? itu frekuensi bukan frekuensi suaranya ya? ato gmn? sy mohon penjelasan

  16. Memang benar range suara yang dapat didengar manusia antara 20 Hz-20 KHz. Sample rate adalah jumlah sample data yang yang diambil tiap detik, sample rate bukan frekuensi suara tersebut.

  17. Sebagai tambahan, coba isi parameter Frequency pada GenerateToneToStream() dengan nilai 20000 Hz atau lebih. Bisakah Anda mendengar bunyi tonenya?

  18. masi bisa dennger frekuensi diatas 20000 hz

  19. heebaaat…mas..saya ikhsan dari palembang nighh…
    aku udah bergelut dengan delphi sudah sekitar 7tahun..tapi ilmunya masih dangkal nih…pengen nanya???boleh ya mas??
    ini ada 1 tabel untuk php,tabel itu masih berbentuk tulisan di notepad..kalo dibuat lewat php…udah bisa..tapi kalo pake delphi..caranya gimana yaa..mas..apakah harus pake sql server???trus digimanain?tolong mas..ilmunya.aku kebinggungan caranya,,kalo bisa kirimin ke email aku ya,…mas

  20. artikelnya bagus, trimakasih.

  21. pak, gimana kalau mau generate data biner menjadi spectrum signal biar bisa di selipkan ke dalam 1 file wave ?? untuk stegano-audio.. hehe

  22. aslmkm. pa kbr mas….. eh aku mau tanya mas gmn rumus tuk menentukan bilangan genap dan ganjil pada delphi hingga pada saat nulis angka ganjil pada kotak edit mka pd kotak maka pada kotak lain kan ada kata2′ bilangan ganjil’
    thanks kpl gw dah gw ptr tp kg nemu2 pdhl tuk hr sbt pleeeeeeessssss help

  23. Mas, bisa bantuin nda?
    Saya perlu source coding gimana mendapatkan nilai tiap-tiap titik diskret,seperti yang mas tulis untuk data 8 bit, range amplitudo adalah 0 (min)-255 (max) dimana 127 adalah silence. Nah gimna cara nya?
    Misalkan samplerate 8000Hz, jd kan ada 8000 titik tiap detik, gimana mengetahui nilai masing-masing titik?
    Thanks banget bantuannya…

  24. Mas…bisa mintatolong gmn cr baca amplitudo sm waktu untuk file .wav

    terima kasih sebelumnya untuk saranya ^-^

  25. asskum. .
    mas mau tanya kalo mau nampilkan spectrum wave pake VCL apa?
    n kasih contohnya ya. .
    THX B4

  26. mas. saya pengen kalo nge-run form delphi saya ada lagunya.. gimana cara nya>??? blz ya.. lewat e-mail lebih baik

  27. wah, nice share nih…
    tp sayang mas, source code kok gak bisa download ya ??
    klo berkenan tolong share via email donk mas🙂

    terima kasih ya sblmnya
    sukses selalu🙂

  28. Kalau codingan penjumlahan bilangan biner sperti apa?

  29. coding ini dapat diterapkan untuk sistem pendeteksi,,, jadi ketika terdeteksi beep ini berbunyi,,, ? coding utama ataupun komponen tambahan yang diperlukan apa saja ya mas,,, mhon penjelasannya,, tmksh,,


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.
Entries and comments feeds.

%d bloggers like this: