Entwickler-Ecke

Multimedia / Grafik - Töne über Soundkarte ausgeben


Hendrik - So 07.07.02 14:44
Titel: Töne über Soundkarte ausgeben
Hallo
Wie kann ich Töne (Dauer, Frequenz) über die Soundkarte ausgeben?


Horst - Do 18.07.02 20:51
Titel: Re: Töne über Soundkarte ausgeben
Hendrik hat folgendes geschrieben:
Hallo
Wie kann ich Töne (Dauer, Frequenz) über die Soundkarte ausgeben?


wieso Töne? Warum nicht Sounds. Sounds lassen sich recht einfach mit der TMediaPlayer-Komponente ausgeben, oder wolltest du ein Synthesizer-Programm schreiben :?:


Hendrik - Do 18.07.02 21:27

Ich möchte Töne ausgeben mit bestimmter Frequenz und Dauer. Keine Sounds(wie z.B. *.wav Dateien) ausgeben.


lordquake - Do 15.08.02 22:15

geht allerings über den pc speaker!!! ein freund meinte das soll irgendwe auch mit soundkarten gehen

Quelltext
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:
procedure WinSound(freq,time:word);
var li : LongInt;
    b  : Byte;
begin
   if freq > 18 then begin
     freq := Word(1193181 div LongInt(Freq));
     B := GetPort($61);
     if (B and 3) = 0 then begin
       SetPort($61,B or 3);
       SetPort($43,$B6);
     end;
     SetPort($42,Freq);
     SetPort($42,Freq shr 8);
   end;
   li:=GetTickCount;
   repeat
      Application.ProcessMessages;
   until ((GetTickCount-li) >= LongInt(time));
   // Ruhe ...
   SetPort($61,GetPort($61) and $FC);
end;


procedure TForm1.Label14Click(Sender: TObject);
begin
  WinSound(1500,100);  {Integerwerte!!!!  was dauer und was frequenz ist  hab ich vergessen, dürfte allerdings nicht schwer rauszufinden sein 
;-) }
end;


toms - Do 15.08.02 22:26

Hi,

So kannst du Töne über den Soundblaster ausgeben:

Quelltext
1:
2:
3:
procedure MakeSound(Frequency{Hz}, Duration{mSec}: Integer; Volume: TVolumeLevel); 
//...
end;


http://www.swissdelphicenter.ch/de/showcode.php?id=1324

tom


lordquake - Do 15.08.02 22:26

ja hab verennt das da schon oben in der externen procedure ja procedure WinSound(freq,time:word); FREQUENZ und DAUER steht

und statt integer es longint ist aber egal nobody is perfect


cbs - Do 15.08.02 22:53

Tag auch

nur so nebenbei:

lordquake hat folgendes geschrieben:
und statt integer es longint ist

integer ist genau der gleiche typ wie longint (32Bit) ganzzahl mit vorzeichen

nur integer ist ein generischer datentyp und longint ein fundamentaler datentyp

der unteschied ist der das generische datentypen vom aktuellen compiler abhängig sind, im moment sind es bei delphi 32 Bit. wären es 64 Bit dann würde integer auch 64 Bit groß sein, longint hingegen bleibt bei 32Bit

generiche datentypen sind also vom aktuellen compiler abhängig (auch cardinal -> gegenstück ist longword), wärend fundamentale datentypen in der jeweiligen sprache "fest" definiert sind

ich hoffe die ausführung war richtig :wink:

nachtrag:
du schreibst hier:

lordquake hat folgendes geschrieben:
WinSound(1500,100); {Integerwerte!!!! ...

hier sind beide werte weder als integer noch als longint deklariert, sondern als word


Hendrik - Fr 16.08.02 16:08

Welche Unit muss ich denn oben einfügen damit das geht. Mit mmsystem hab ich´s schon probiert.


NightHawk - Mo 26.08.02 22:30

Hi,

Du hast nicht geschrieben, wie professionell du dabei vorgehen möchtest. Willst du mehrere Stimmen wiedergeben, dann bleibt dir nichts anderes übrig, als zu mischen oder DirectX zu verwenden. Willst du verschiedene Wellenformen (Sägezahn, Sinus, Quadrat usw.), dann wird es ein wenig komplizierter....

Du schreibst ausserdem, dass du keine WAV-Dateien wiederegben möchtest. Warum denn nicht??? WAV-Dateien brauchst du nicht zu laden. Falls du nur eine Sinus-Welle spielen möchtest, brauchst du nur eine WAV-Structur zu erstellen (TWaveHdr) und diese mit einem bestimmten Format (TWaveFormatEx) abzuspielen. Falls du diese Sinuskurve loopen tust (TWaveHeader.dwLoop = -1), dann hast du einen ewig langen ton. Die Sinuskurve selbst kannst du anhand einer Formel, wie:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
r: single;
WaveHeader: TWaveHdr;
GetMem(WaveHeader.lpData, 440);

r := 0;
WaveHeader.dwBufferLength = 440;

for i = 0 to 440-1 do
begin
   PByte(WaveHeader.lpData)[i]^ = Sin(r) * 127 + 128;
   r := r + 360 / 440;
end;

(naja, auf diese Formel (8Bit 44100Khz Mono) keine Gewähr. Probier mal lieber ein wenig rum)

Nun kannst du in einer Routine die Tonlänge abfragen und anhand vom Volume den Ton abklingen oder aufklinen lassen. Du kannst natürlich auch mit der Frequenz spielen. Dazu lies dir doch die MMSystem-Doku durch. Falls du nicht weiterkommst, schreib nochmal.

Übrigens: Willst du mehrere Stimmen, dann nimm DirectX und erstelle mehrere SoundBuffer, mit denen du im selben Verfahern wie hier, Töne ausgibst. So schwierig ist das nicht. Ich denke, dass ca. 20 Zeilen für deine Zwecke genügen sollten.

Ansonsten: ...solltest du es dir gut überlegen, ob es sinnvoll ist, in einem Multimedia-Betriebssystem noch Daten direkt an einen Port zu senden....

Grüsse

NightHawk


Hendrik - Di 27.08.02 15:44

Also ich will einfach nur einen konstanten Ton z.B. 1530Hz über eine Zeit von 70 ms ausgeben, danach soll ein anderer Ton folgen usw.