Delphi-PRAXiS
Seite 3 von 7     123 45     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   wie kann ich viele kurze töne schnell hintereinander spielen (https://www.delphipraxis.net/76369-wie-kann-ich-viele-kurze-toene-schnell-hintereinander-spielen.html)

igel457 7. Sep 2006 17:56

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Das musst du einfach in eine WAV Datei schreiben.
Delphi-Quellcode:
procedure MakeSound(Duration{mSec}: Integer);
  {writes tone to memory and plays it}
var
  WaveFormatEx: TWaveFormatEx;
  MS: TMemoryStream;
  i, TempInt, DataCount, RiffCount: integer;
  SoundValue: byte;
  w: double; // omega ( 2 * pi * frequency)
const
  Mono: Word = $0001;
  SampleRate: Integer = 11025; // 8000, 11025, 22050, or 44100 <--Hier Samplerate einsetzen
  RiffId: string = 'RIFF';
  WaveId: string = 'WAVE';
  FmtId: string = 'fmt ';
  DataId: string = 'data';
begin
  with WaveFormatEx do
  begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := Mono;
    nSamplesPerSec := SampleRate;
    wBitsPerSample := $0032;
    nBlockAlign := (nChannels * wBitsPerSample) div 8;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;
  MS := TMemoryStream.Create;
  with MS do
  begin
    {Calculate length of sound data and of file data}
    DataCount := (Duration * SampleRate) div 1000; // sound data
    RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +
      SizeOf(TWaveFormatEx) + Length(DataId) + SizeOf(DWORD) + DataCount; // file data
    {write out the wave header}
    Write(RiffId[1], 4); // 'RIFF'
    Write(RiffCount, SizeOf(DWORD)); // file data size
    Write(WaveId[1], Length(WaveId)); // 'WAVE'
    Write(FmtId[1], Length(FmtId)); // 'fmt '
    TempInt := SizeOf(TWaveFormatEx);
    Write(TempInt, SizeOf(DWORD)); // TWaveFormat data size
    Write(WaveFormatEx, SizeOf(TWaveFormatEx)); // WaveFormatEx record
    Write(DataId[1], Length(DataId)); // 'data'
    Write(DataCount, SizeOf(DWORD)); // sound data size
    {calculate and write out the tone signal} // now the data values
    w := 2 * Pi * Frequency; // omega
    for i := 0 to ListBox1.Count-1 do
    begin
      Write(StrToFloat(ListBox1.Items[i]),32);
    end;
    {now play the sound}
    sndPlaySound(MS.Memory, SND_MEMORY or SND_SYNC);
    MS.Free;
  end;
end;
Du musst halt ein wenig mit der Sample-Größe und der Frequenz spielen.

3_of_8 7. Sep 2006 18:40

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Man muss allerdings dazusagen, dass sich die Dateigröße in etwa verfünffacht bei diesem Format.

igel457 7. Sep 2006 18:46

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Zitat:

Zitat von 3_of_8
Man muss allerdings dazusagen, dass sich die Dateigröße in etwa verfünffacht bei diesem Format.

Ich frage mich überhaupt, für was man so ein Format braucht. Wer schreibt schon "per Hand" Sounds?

Was ich oben noch vergessen habe, ist dass du dir Duration noch ausrechnen musst. Und zwar mit SampleRate/SampleCount.

dino 7. Sep 2006 19:49

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
stellt euch vor, man gab mir einen richtig schönen sound und ich tat mir Arbeit an, um die Datenmengen zu verfünffachen, während die Tonqualität runter geht.
mir geht es wirklich nicht hauptsächlich um das hören, ich will aber verstehen, wie solche Werte einen Ton geben, und auch Delphi beibringen "Ja" von "Nein" zu unterscheiden

fwsp 7. Sep 2006 19:53

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
ein "sound", besser klang, entsteht, wenn eine menge an frequenzen interagieren. es ist nicht möglich daraus töne zumachen. jedenfalls nicht so, wie du dir das vorstellst. die musik kannst du so nicht entzaubern.

dino 7. Sep 2006 23:29

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Goldwave kann alle sampels(vertrau mal,dass die werte so heisse) schnell hintereinander spielen un daraus ergibt sich ein Ton.
Dass das nicht leicht ist, ist mir klar, aber wenn man sich ein wenig auskennt, müsste es doch Möglich sein aus den samples Frequenzen zu errechnen

3_of_8 7. Sep 2006 23:36

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Also ich bin 1. müde und hab 2. keine Ahnung.

Ich schreib jetzt hier trotzdem mal.

Ich glaube, dass diese Zahlen keine Töne sind, sondern die Oszillation des Lautsprechers/Mikrofons zu einem bestimmten Moment darstellen. Bei 44,1 kHz die Oszillation in 0,0226ms-Abständen. Du kannst daher also nicht einfach mithilfe von ein paar Sinustönen ein Geräusch abspielen, sondern du brauchst dazu nunmal eine Möglichkeit, diese Oszillationsdaten wiederzugeben. Du stellst dir das alles viel zu einfach vor.

grizzly 8. Sep 2006 07:11

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Wow: Bis gerade eben wußte ich gar nicht, daß man in GoldWave Sounddaten auch als ASCII ausgeben kann. Man lernt immer noch dazu.

Um alle Samples der Text-Datei "schnell hintereinander" abzuspielen ist es also am einfachsten folgendes zu machen:
1. Die Textdatei mit den Audiodaten (den Samples) in Goldwave laden.
2. Die Audiodatei als WAV abspeichern.
3. Die Wav Datei in Delphi mit SndPlaySound abspielen. (Ja, das ist wirklich nichts anderes als alle Samples (nicht Töne) in der angegebenen Geschwindigkeit schnell hintereinander abzuspielen)

Wenn es doch die harte Tour sein soll, dann funktioniert der Code von igel457 durchaus. Ein paar klitzekleine Anpassungen, eine Listbox und einen Button auf die Form, und ich konnte mir das Gezirpe auch mit Delphi anhören:

Delphi-Quellcode:
procedure TForm1.MakeSound;
  {Reads data from ListBox1, writes tone to memory and plays it}
var
  WaveFormatEx: TWaveFormatEx;
  MS: TMemoryStream;
  i, TempInt, DataCount, RiffCount: integer;
  SoundValue: byte;
  w: double; // omega ( 2 * pi * frequency)
  Sample: smallint;
const
  Mono: Word = $0001;
  // Eigentlich müßte man hier aus der ersten Zeile der Listbox die Infos zu Abspielfrequenz auslesen anstatt hart 22050 zu setzen
  SampleRate: Integer = 22050; // 8000, 11025, 22050, or 44100 <--Hier Samplerate einsetzen
  RiffId: string = 'RIFF';
  WaveId: string = 'WAVE';
  FmtId: string = 'fmt ';
  DataId: string = 'data';
begin
  with WaveFormatEx do
  begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := Mono;
    nSamplesPerSec := SampleRate;
    wBitsPerSample := $0010;
    nBlockAlign := (nChannels * wBitsPerSample) div 8;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;
  MS := TMemoryStream.Create;
  with MS do
  begin
    {Calculate length of sound data and of file data}
    DataCount := ListBox1.Items.Count-1; // sound data from Listbox
    RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +
      SizeOf(TWaveFormatEx) + Length(DataId) + SizeOf(DWORD) + DataCount; // file data
    {write out the wave header}
    Write(RiffId[1], 4); // 'RIFF'
    Write(RiffCount, SizeOf(DWORD)); // file data size
    Write(WaveId[1], Length(WaveId)); // 'WAVE'
    Write(FmtId[1], Length(FmtId)); // 'fmt '
    TempInt := SizeOf(TWaveFormatEx);
    Write(TempInt, SizeOf(DWORD)); // TWaveFormat data size
    Write(WaveFormatEx, SizeOf(TWaveFormatEx)); // WaveFormatEx record
    Write(DataId[1], Length(DataId)); // 'data'
    Write(DataCount, SizeOf(DWORD)); // sound data size
    {calculate and write out the tone signal} // now the data values
    //w := 2 * Pi * Frequency; // omega
    DecimalSeparator := '.';
    for i := 1 to ListBox1.Count-1 do
    begin
     // Sample := round(StrToFloat(ListBox1.Items[i])*127)+128;
       Sample := round(StrToFloat(ListBox1.Items[i])*32767);
      Write(Sample,SizeOf(Sample));
    end;
    {now play the sound}
    sndPlaySound(MS.Memory, SND_MEMORY or SND_SYNC);
    MS.Free;
  end;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.LoadFromFile('c:\temp\test-1.txt');
  MakeSound;
end;
Ich weiß nur nicht, ob es die MemoryStreams schon in Delphi3 gegeben hat...

Gruß
Michael

Edit 09.09.2006: vlees91 hat natürlich recht, das Aufruf von MakeSound erfolgt natürlich ohne Parameter. Hab' mal wieder zwei unterschiedliche Code-Zustände zusammenkopiert. Sorry.

vlees91 8. Sep 2006 16:26

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
MakeSound erwqartet bei dir doch keine Parameter?!

grizzly 9. Sep 2006 06:20

Re: wie kann ich viele kurze töne schnell hintereinander spi
 
Den Parameter hatte ich rausgeworfen, weil man die wichtigen Infos im gegebenen Fall eigentlich aus der ersten Zeile der Daten in der ListBox ("[ASCII 22050Hz, Channels: 1, Samples: 87556, Flags: 0]") holen müßte. Vielleicht hätte man der Prozedur auch gleich eine TStringList als Parameter übergeben können.
Aber all das hatte ich mir verkniffen. Ich wollte nur ganz flott mit igel457's Code etwas an meinen Lautsprechern hören. Nur um zu sehen, daß das ursprüngliche Problem eh schon lang gelöst war (3_of_8 WAV-Vorschlag oder igel457 ASCII to WAV Routine etc.) und die ganze nächtliche Diskussion in diesem Thread sich ein wenig verirrt hatte...

Gruß
Michael

Edit: (5 Minuten später...) Jetzt hab' ich es erst bemerkt, worauf vlees91 anspielt. In meiner Code-Kopie weiter oben war noch ein Parameter drin beim Aufruf von MakeSound. Ist natürlich Quatsch. Sorry. Mitternacht ist halt zu spät, aber 8 Uhr scheinbar auch zu früh...
Code editiert...


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:45 Uhr.
Seite 3 von 7     123 45     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz