![]() |
Sound ausgabe 40 mal in der Sekunde
Hallo :wink:
Da dies mein erster Beitrag in diesem super Forum ist (bisher habe ich immer nur mitgelesen :cyclops: ) möchte ich erstmal Hallo sagen :thumb: . Hallo :hi: So und nun zu meinem Problem: Also, ich möchte ein Programm schreiben, das im wesentlichen Sounds ausgibt (auf meinen Befehl). Bis hierhin nicht weiter schwierig, aber: Der abgespielte Sound soll 40 mal in der Sekunde ab und angeschaltet werden können und das ist in der Tat nicht so einfach, da selbst präzisere Timer Probleme zu haben scheinen. Ich glaube aber, das dass Problem nicht an den Timern selber liegt, sondern vielmehr an der Verarbeitung des Sounds. Damit meine ich, dass die Zeitspanne des Ladens und Stoppens des Sounds zu lange dauert. Ich habs mit wav dateien probiert aber keinen Erfolg gehabt. Dann bin ich auf die Komponente ToneGen gestoßen, damit ging es etwas besser, aber zufriedenstellend war das auch nicht. Der Sound lässt sich schätzungsweise 15-20 mal zuverlässig in der Sekunde Triggern. Das Programm soll am Ende den erzeugten Sound einfach als wav datei abspeichern. Ich möchte über eine bestimmte Zeitspanne die Hz Rate durch knopfdruck wechseln lassen. Das soll möglichst dynamisch sein. Die Rate möchte ich zum beispiel in 3 Sekunden um 10 Herz linear erhöhen oder von 30 auf 40 Herz setzten etc. . Das wird dann in Echtzeit aufgezeichnet. Der Sound an sich besteht dabei nur aus einer einfachen Sinuskurve, die sich eben zum Beispiel mit Tonegen erzeugen lässt. Habt ihr Ideen, wie ich das mit dem an - aus Problem lösen könnte ? Danke :-D Six |
Re: Sound ausgabe 40 mal in der Sekunde
Herzlich willkommen bei der Delphi-Praxis.
Ich glaube nicht das du auf diesem weg wirklich weiterkommst. Wie waere es denn einen WAV Sound mit den Aenderungen vorzuberechnen und einfach abzuspielen? Das sollte moeglich sein, allerdings sit das Soundverarbeitung von dem ich keine Ahnung habe. |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Mit play-stop-play-stop wirst du wenig Erfolg haben. Entweder du berechnest den ganzen Sound vorab und gibst ihn da wieder (einfacher zu Coden) oder du berechnest den Anfang (ein paar Sekunden), startest die Wiedergabe und berechnest währenddessen den Rest. Wenn du das Ergebnis dann berechnet hast, kannst du es dann auch als WAV speichern. Mfg FAlter |
Re: Sound ausgabe 40 mal in der Sekunde
Erstmal danke für die Antworten :thumb:
Zitat:
Gruß Six |
Re: Sound ausgabe 40 mal in der Sekunde
Mit Turbo Pascal kann man glab' ich über
Delphi-Quellcode:
Sound aus dem integriertem Lautsprecher ausgeben.
Sound(Frequenz);
Delay(Dauer); NoSound; Dann mit ner Schleife oder so arbeiten. Wenns dir was bringt ... :wink: Florian |
Re: Sound ausgabe 40 mal in der Sekunde
Hi Florian,
danke für den Tipp, aber leider bringt mir das nicht viel, da ich eine bestimmte Sinuskurve über die Standardlautsprecher ausgeben und vor allem auch aufzeichnen möchte. Wahrscheinlich wäre auch diese Funktion zu langsam. Das Problem ist die Vorrausberechnung. Kennt da irgendjemand ein Tutorial zu oder ähnliches? Irgend etwas über fortgeschrittene Soundbearbeitung in Delphi... Audiacity ist ja leider in C++ verfasst und sich da einzuarbeiten ist für diesen Zweck leider auch ein bischen zu aufwendig... Aber wenn es sowas wie Audiacity in Delphi als open Source geben würde (kann ja auch viel einfacher sein), wäre mir schon sehr geholfen. Ich habe nur leider nichts in der Art gefunden. Six |
Re: Sound ausgabe 40 mal in der Sekunde
Tutorial kenn ich nicht, habs aber schonmal probiert. Ist eigentlich nicht schwer. Hier mal die Vorausberechnung eines Sinustones:
Delphi-Quellcode:
uses
MMSystem; var Format: TWaveFormatEx; Size: Longint; Data: PSmallInt; //für 8 Bit PByte verwenden Um TWaveFormatEx mit gültigen Daten für ein PCM-Format (Pulse Code Modulation) zu füllen, habe ich mir das geschrieben (auch Bestandteil meiner Sound.dll)
Delphi-Quellcode:
Dann setzt du Size auf einen bestimmten Wert:
{ Gültig sind: bei Bitrate = 8 ein oder zwei Channels,
bei 16 Bit ein, zwei oder vier Channels, Sampleraten zwischen 100 Hz (nicht empfohlen!) und 10 kHz (= 10000 Hz)). Sampleraten in Hz angeben. } function WavePCMFormat(const Channels, Bitrate: Word; const Samplerate: DWord): TWaveFormatEx; begin with Result do begin nChannels := Channels; wFormatTag := WAVE_FORMAT_PCM; nSamplesPerSec := Samplerate; wBitsPerSample := Bitrate; nBlockAlign := nChannels * WBitsPerSample div 8; nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; cbSize := 0; end; end;
Delphi-Quellcode:
Wobei Sekunden irgendeine Zahl ist (z. B. Double). Wenn du nur mit ganzen Sekunden arbeitest (Integer), kannst du das Round weglassen.
Size := Round(Sekunden * nAvgBytesPerSec);
Dann musst du den Speicher reservieren:
Delphi-Quellcode:
Um nun die Sinuskurve zu erstellen, brauchst du eine Zählschleife:
GetMem(Data, Size);
Delphi-Quellcode:
Freq ist hierbei die gewünschte Frequent (z. B. 440 Hz fpr dier Note a'), es kann Douible oder Extended sein.
//für 8 Bit abwandeln!!
X := Data; //X ist auch ain PSmallInt! for I := (Size div 2) - 1 downto 0 do begin X^ := Round(Sin(Y * Freq * Pi * 4 / Format.nAvgBytesPerSec) * 32767); inc(X); end; Zur Wiedergabe kannst du dann z. B. DirectSound verwenden. Da musst du meist Format oder @Format, Size und Data übergeben. Für den Anfang ist DelphiX sehr einfacvh, wenn es auch veraltet ist und nicht mehr weiterentwickelt wird, aber bei DirectSound hat sich seitdem noch nicht viel geändert (im Gegensatz zu Direct3D). |
Re: Sound ausgabe 40 mal in der Sekunde
also dein Vorhaben wird mit aller wahrscheinlichkeit scheitern. Professionelle Programme welche einen extra Treiber mitbringen der im Kernelbereich arbeitet oder Programme die im RealTimeModus arbeiten kommen in aller Regel bei der Latenz nicht unter 2 ms. Wenn du den DirectSound-Treiber von Windows verwendest so liegt die Latenz irgendwo um die 100 ms.
|
Re: Sound ausgabe 40 mal in der Sekunde
@ SirThornberry:
Ja, ich denke mittlerweile auch, dass es in Echtzeit scheitern wird, daher bin ich ja auch an der Möglichkeit interessiert, die Falter mir gerade versucht zu erklären. @ Falter: Danke für die Antwort. Ich muss nur leider zugeben, dass ich von dem ganzen Sound zeugs wie gesagt, leider keine Ahnung habe und hier im Moment nur Bahnhof verstehe :stupid: Aber vielleicht steige ich da ja irgendwie durch. Du schreibst, dass Sampleraten (ich nehme an, das ist die höhe des Tons) zwischen 100Hz und 10Khz möglich sind. Ich bräuchte aber um die 22Khz, ist das irgendwie zu bewerkstelligen (liegt nicht mehr im höhrbaren Bereich und soll auch nicht höhrbar sein)? Was ist diese Sound Dll von der du sprichst, brauche ich die um den Code auszuführen? Brauche ich DelphiX um den Code auszuführen? Kann man die Sinuskurve nicht irgendwie so berechnen, das einmal ein Ton hörbar ist und dann wider für eine bestimmte zeit nicht, dann kommt wieder ein Ton etc.? So wie auf den Herzfrequenzmessern im Krankenhaus? Sorry, dass hört sich jetzt alles ziemlich dämlich an, aber es ist mein erstes Projekt in der Richtung und leider fehlen mir da auch einfachste Grundlagen. Wie hast du dir dein Wissen angeeigenet? Gruß Six |
Re: Sound ausgabe 40 mal in der Sekunde
Zitat:
Zitat:
Delphi-Quellcode:
Ansonsteh hätte ich sie dir empfohlen... Aber erst muss die Exception weg, da sonst das gesamte Programm (das die DLL geladen hat), beendet wird :(
procedure ...(...); stdcall;
var ... begin ... end; // <-- HIER Zitat:
Vielleicht wäre es praktisch, wenn du verstehst, wie Audiodaten im PCM-Format aufgebaut sind... Nehmen wir an, du hast zwei digitale Spannungsmesser an eine Audioquella engeschlossen und misst jetzt in jeder Seklunde 22050 mal die Spannung, ein Spannungsmessetr rechts und einen links. Die Spannungsmesser bringen 16-Bit-Werte zwischen -3,2768 V* und 3,2768 V*. Du multiplizierst sie mit 10000 und speicherst sie nacheinander ab, erst links, dann rechts, dann den nächsten Messwert... Damit hast du dein Geräusch als PCM-Rohdaten. Zur Wiedergabe wird an den Soundkartenausgang mit den gleicghen Zeitabständen wie bei der Aufnahme die vorher gemessene und dann gespeicherte Spannung angelegt. Mit einem Leistungs-Verstärker in deiner aktiven Lautsprecherbox kannst du die Lautsprecher mit hohen Leistungen ansteuern und somit ganz laut Musik oder andere Klänge wiedergeben. Jetzt fällt der Schritt der Aufnahme weg, du erzeugst selbst den Ton, mit Zuhilfenahme der Sinusfunktion. PS: Ich kann hier für Richtigkeiten keine Gewähr geben. Ich habe das Prinzip, Töne in den Speicher zu schreiben, durch eigebnes Ausprobieren entdeckt, ohne irgendwo zu lesen. Bei mkir hat es zumindest funktioniert. ________ *) Es wird i. d. R. mit Spannungen unter 1 V gearbeitet (775 mV wäre Standard, wird aber meist nicht ganz eingehalten), das hier war nur zur einfacheren Veranschaulichung. |
Re: Sound ausgabe 40 mal in der Sekunde
Hi FAlter,
Danke für deine Hilfe :thumb: Könntest du mir dafür vielleicht noch mal ein kleines Codebeispiel geben (möglichst Lauffähig): Zitat:
Besten Dank! Six |
Re: Sound ausgabe 40 mal in der Sekunde
Liste der Anhänge anzeigen (Anzahl: 2)
Hier erstmal ein Beispiel MIT sound.dll, eventuell solltest du die nächste Zeit mal nachsehen, ob eine neue Version herausgekommen ist. Ein Beispiel ohne DLL werde ich eventuell nach dem Zelten nachliefern. (Das reimt sich ja!)
Ansonsten versuch es einfach mal selbst oder nehm zur Wiedergabe sowas einfaches wie DelphiX (denn es ist nur die Wiedergabe, die nicht ganz reibungslos funktioniert, also PlayPCMMemory). So, ich fahr jetzt zelten! :hello: :hi: CU :hi: :hello: |
Re: Sound ausgabe 40 mal in der Sekunde
Sorry, dass ich mich so lange nicht gemeldet hatte, aber ich hatte in letzter Zeit keinen Internet Zugang.
@ Falter: Danke für die Hilfe und deine Dateien! Ich hoffe ich komme in nächster Zeit mal dazu das ganze auszuprobieren. Ich würde mich gerne noch weiter in das Thema einarbeiten, habe aber wie gesagt, keine kostenlosen tutorials etc. gefunden. Hat sich denn außer Falter noch niemand mit dem Thema Soundbearbeitung und Delphi auseinandergesetzt? :gruebel: Six |
Re: Sound ausgabe 40 mal in der Sekunde
Soooo, also ich habe jetzt ein wenig mit deinem Beispiel (Danke, Danke Danke :mrgreen: ) herumprobiert und stellte fest, dass damit eine 40 Hz Frequenz wirklich kein Problem ist :thumb:
Den Ton an sich soll man übrigens nicht hören können, da er nur als Signal dient. Jetzt habe ich allerdings ein Problem. Ich habe zunächst Sinus auf Square gesetzt nur höre ich jetzt bei jedem Ein- und Ausschaltvorgang ein Knacken (auch bei Sine). Es ist ganz wichtig für mich, die Steuerung komplett lautlos zu machen, wie bekomme ich also dieses Knacksen weg? Und: Wie kann ich den linken und rechten Kanal getrennt steuern? Zum beispiel möchte ich den rechten Kanal 10 mal in der Sekunde und den linken Kanal 20 mal in der Sekunde Ein- und Ausschalten lassen. Ist das irgendwie möglich? Danke für eure Hilfe! Six |
Re: Sound ausgabe 40 mal in der Sekunde
Wenn TWaveFormatEx.Channels auf 2 steht, wechseln sich immer linker und rechter Channel ab, also bei 22050 Hz hast du 44100 Smallint-Werte in einer Sekunde Daten. Der erste ist links, Sample 1, der zweite ist rechts, Sample1, dann links Sample 2...
Überleg dir selbst was oder mach zwei Mono-Sounds wie zuvor dargestellt und mische sie dann zusammen (doppelt so viel Speicer wählen und dann abwechselnd Werte von einem und anderen Stream nehmen, in Zählschleife etwa
Delphi-Quellcode:
//edit: Siehe Quellcode :oops: ich glaube ich sollte mit 'nen Shortcut für den :oops: anlegen :D
//Size = Größe der Quellsounds (beide gleich)
//ziel, quelle1, quelle2 wieder PSmallInt GetMem(ziel, 2*size); for i := (Size div 2) - 1 downto 0 do //div 2 wegen 16 Bit = 2 Bytes begin ziel^ := quelle1^; inc(Ziel); ziel^ := quelle2^; inc(Ziel); // <-- edit: ergänzt, fehlte end; |
Re: Sound ausgabe 40 mal in der Sekunde
Ok, danke, werde ich probieren.
Aber hast du auch eine Idee, wie ich das knacksen vermeiden kann? Wenn ich das nicht wegbekomme, ist die ganze Sache leider unbrauchbar :pale: mfg Six |
Re: Sound ausgabe 40 mal in der Sekunde
Naja, bei meinem Beispiel hör ich kein Kancksen...
Aber vermutlich hast du zufälligerweise eine Unterbrechung an einer Stelle der Sinuskurve, an der keine Nullstelle ist (beim Rechtecksignal gibt es keine Nullstellen, sondern einen direkten Wechsel des Vorzeichens, aber das Problem sollte das gleiche sein: Unterbrechung des Sounds an falscher Stelle). Du könntest die Zeit der Unterbrechung unwesentlich ändern, so, dass der User es nicht merkt, aber die Zeitpunkte der Nullstellen der Funktion (bzw. bei Rechteck die Zeitpunkte des Wechsels zwischen den Vorzeichen, sind dieselben Zeitpunkte wie die Nullstellen bei Sinus) den Zeitpunkten beim ein- bzw. ausschalten des Tones entsprechen. Bei einer "normalen" Sinusfunktion kommen die Nullstellen bei allen ganzzahligen Vielfachen von Pi. Dank unserer netten Sinusfunktion
Delphi-Quellcode:
ist das hier ein wenig abgewandelt. Jede halbe Schwingungsdauer kommt eine Nullstelle, wobei eine Schwingungsdauer der Kehrwert der Frequenz ist. Bei einer Frequenz von 1 Hz ist die Schwingungsdauer 1 Sekunde, das heißt, der Nullpunkt wird alle 0,5 s durchlaufen.
Sin(Y * Freq * Pi * 4 / Format.nAvgBytesPerSec)
Sorge also dafür, dass deine An/Aus-Vorgänge an (1 / Frequenz / 2) ausgerichtet werden. (Voraussetzung: Die An-Aus-Frequenz ist kleiner als die Tonfrequenz). Eine andere Alternative sind Fade-in und Fade-out über nur sehr wenige Samples. Ein Fade-in bzw. Fade-out ist das lauter- bzw. leiserwerden des Tones. So könntest du z. B. dein gesamtes Werk lauter werden lassen:
Delphi-Quellcode:
Das ganze musst du so abwandeln, dass es nur einige wenige Samples entspricht, eventuell eine halbe oder eine viertel Schwingungsdauer der Tonfrequenz, und dass es an jedem Einschaltvorgang kommt.
procedure FadeInPCM16Bit(Data: PSmallInt; Size: Integer);
var I: Integer; DataLength: Integer; begin DataLength := Size div 2; for I := 1 to DataLength do begin Data^ := Data^ * I div DataLength; inc(Data); end; end; Analog lassen sich Ausschaltvorgänge mit Fade-out realisieren... Da musst du nur die Richtung der Zählschleife umkehren... Diese dann für die Ausschaltvorgänge abwandeln...
Delphi-Quellcode:
PS: Sources nicht getestet ;) gilt auch für vorigen Post.
procedure FadeInPCM16Bit(Data: PSmallInt; Size: Integer);
var I: Integer; DataLength: Integer; begin DataLength := Size div 2; for I := DataLength - 1 downto 0 do //downto 0 ist schneller als downto 1 und der //Unterschied ist für Menschen nicht hörbar ;) begin Data^ := Data^ * I div DataLength; inc(Data); end; end; //edit: uns schon die ersten Fehler gefunden :oops: //edit2: Hab mal den Fadein-Code getestet.. hört sich scheißlich an, irgendwo kommt es da zu einem Überlauf? Data^ * I dürfte das Problem sein, delphi Rechnet das zwar intern mit 32 Bit aus und dividiert danach, aber wenn I zu groß ist... Meinetwegen rechne mit Int64-Werten, und wenn das nicht funktioniert... rechne mit Extended-Werten und verwende dann Round. |
Re: Sound ausgabe 40 mal in der Sekunde
Danke Falter!
Ich hoffe, ich kann das auch mit dem Rechtecksignal verwenden. Da meine Frequenz bei 22000Hz liegt, sollten eigentlich genügend Nullstellen vorhanden sein. Das Rechtecksignal eignet sich für meine Zwecke deutlich besser. Ich habe deinen Code ein wenig abgeändert, da er bei höheren Frequenzen nicht mehr funktioniert hat:
Delphi-Quellcode:
Das entpricht etwa 10 Ein- und Ausschaltzyklen in der Sekunde.
for I := 1 to (Size div Format.nChannels) do
begin if I mod 4450 = 0 then Aus := not Aus; if Aus then Data2^ := 0; inc(Data2); end; Würde das alles eigentlich auch mit der Bass.dll funktionieren oder wäre das ganze auch ganz ohne Dll möglich? Ich frage, weil mir durch die Dll viele Dinge verborgen bleiben, die ich eigentlich wissen müsste, um das ganze etwas besser zu verstehen... Wie hast du dir dein ganzes Wissen in diesem Bereich angeeignet? Ich probiere dann mal die Sache mit dem Knacksen zu beseitigen. Wenn ich keinen Erfolg habe, frage ich nochmal. Wie kann ich zwei Sounds zusammenmischen, also beispielsweise einen 500 Hz und einen 800 Hz Ton, oder zwei wav Dateien? Abermals vielen Dank! Six |
Re: Sound ausgabe 40 mal in der Sekunde
Du kannst auch die Bass.dll verwenden, aber mit der kenn ich mich nicht so aus, aber du siehst ja, dass das ganze hauptsächlich auf Arbeit mit Pointern hinausläuft, und jede gute Audio-DLL unterstützt es, durch Angabe eines Formats, der Größe der Rohdaten und dem Pointer auf die Rohdaten den Sound wiederzugeben.
[ot] Was mich wundert ist, dass du bei 22000 Hz = 22 kHz noch etwas hörst, ab 16 kHz können Menschen einen Ton nämlich gewöhnlcih nciht mehr wahrnehmen. Bist du ein Außerirdischer? Oder eine Mutation? Oder hast du Katzengene? (Unsere Katzen können diese Töne sicher hören, frag mal eine davon...) Oder meintest du die Samplerate? Ich meinte im obigen Post die Frequenz des Tones selbst. Für 16 kHz benötigst du zur Speicherung mindestens 32 kHz Samplerate, aber da gehen noch sehr viele Infos verloren. Deshalb höret sich 8 kHz-Musik so schreklich an, weil alles jenseits von 4 kHz wegfällt und ein großer Teil verzerrt ist. Wenn du mit einer niedrigen Tonfrequenz arbeitest (unter 1 kHz), dann sollten deine 22 kHz Samplerate genügen, und mit 40-Hz-Unterbrechungen sollte es auch keine Probleme mehr geben. [/ot] |
Re: Sound ausgabe 40 mal in der Sekunde
Zitat:
Addiere die Samples der Sounds, wenn sie sehr laut sind, dann bilde den Durchschnitt...
Delphi-Quellcode:
Bei unterschuiedlich langen Sounds fülle den kürzeren am Ende mit Nullsamples...
//Size = Größe der Quellsounds (beide gleich)
//ziel, quelle1, quelle2 wieder PSmallInt GetMem(ziel, 2); for i := (Size div 2) - 1 downto 0 do //div 2 wegen 16 Bit = 2 Bytes begin ziel^ := (quelle1^ + quelle2^) div 2; inc(Ziel); end; //edit: Hatte versehentlich quote- statt delphi-Tags genommen :oopa: <-- der neue Standardsmiley |
Re: Sound ausgabe 40 mal in der Sekunde
Nein, ich bin KEIN Mutant :wink:
und du hast schon recht, wenn wir hier durcheinanderkommen, da ich in zwei verschiedenen Zusammenhängen von Frequenz spreche. Also nochmal zur Verdeutlichung: Der eigentliche Ton hat eine Frequenz von 22000Hz. Den kann und soll natürlich kein Mensch mehr hören, da er als Signal dient, um etwas anderes zu Steuern. Mit 40 Hz beispielsweise meine ich dann die Frequenz, mit der dieser 22000Hz Ton an- und ausgeschaltet wird. Die Samplerate (?) liegt bei 44100 Hz, sonst hört sich der 22000Hz Ton ja nicht an wie er soll, bzw. wird hörbar. In meiner Anwendung, will ich nun diese An- und Ausschaltvorgänge vom Benutzer vorgeben und anschließend abmischen lassen. Dabei rauskommen soll dann eine Datei, mit einem gleichbleibenden Ton von 22000 Hz, der mit unterschiedlichen Frequenzen unterbrochen wird. So, ich hoffe ich habe alle Klarheiten beseitigt :thumb: Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hi Falter,
Also so wie's aussieht komme ich jetzt klar und deshalb markiere ich den Post jetzt erstmal als gelöst. Nochmals vielen Dank, du hast mir die Augen geöffnet :spin: Falls du Lust hast, könntest du ja mal ein Grundlagen Tutorial über die ganze Sache schreiben, leider ist da noch nicht viel in der Richtung verfügbar (eigentlich gar nichts?). Eine Sache gibts aber dennoch, die ich noch nicht verstanden habe:
Delphi-Quellcode:
Warum muss hier die DataLength durch zwei geteilt werden? Entspricht das einem Fade In über die ganze Länge des Sounds?
DataLength := Size div 2;
for I := 1 to DataLength do Hast du eigentlich vor den Source deiner Sound.dll zu veröffentlichen? Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Size entspricht der Größe in Bytes (!), die deine Sounddaten haben. Wenn du mit 16-Bit-Sounds arbeitest, ist eine Teilinformation zwei Bytes groß, das heißt die Gesamtzahl aller Teilinformationen ist die Hälfte der Anzahl der Bytes, da eine Teilinformation doppelt so groß ist (16 statt 8 Bits --> 2 statt 1 Byte). Als Teilinformation verstehe ich hierbei einen Kanal innerhalb eines Samples. Den Source gibts vorerst nicht. Mfg FAlter |
Re: Sound ausgabe 40 mal in der Sekunde
Hi Falter,
Sorry, aber ich brauche noch einmal deine Hilfe... Ich möchte zwei gleich lange Monosounds zu einem Stereosound zusammenmischen. Dabei sollen die Monospuren jeweils dem Linken und rechten Soundkanal der erzeugten Stereodatei entsprechen. Dafür habe ich deinen Code folgendermaßen eingebaut:
Delphi-Quellcode:
Leider bekomme ich bei der Verwendung dieses Codes eine nichtssagende Fehlermeldung und ich glaube auch nicht, dass ich damit zwei Monospuren zu einer Stereodatei zusammenfügen kann, richtig? Ich denke du dachtest, ich wollte zwei Mono- oder Stereosounds mischen. Wie kann ich also zwei Monosounds zu einem Stereosound zusammenmischen?
Quelle1:=Data; // erster Monosound
Quelle2:=Data3; //zweiter Monosound GetMem(ziel, 2*size); for i := (Size div 2) - 2 downto 0 do //div 2 wegen 16 Bit = 2 Bytes begin ziel^ := quelle1^; inc(Ziel); ziel^ := quelle2^; inc(Ziel); // <-- edit: ergänzt, fehlte end; SavePCMMemoryToFile(Ziel, 'C:\Result.wav', Format, Size); //Abspeichern Und noch eine andere Sache ist mir aufgefallen, die ich nicht verstehe: diese Data2:=Data Geschichte... Was ist der Zweck des ganzen, warum kann man nicht einfach direkt mit Data arbeiten? Und dann wird nur noch mit data2 gearbeitet und am ende steht das Ergebnis dann doch wieder in data?! Habe ich da irgendwo eine zweite Zuweisung am Ende übersehen, oder wie geht das (Ich hoffe du verstehst, was ich meine :wink: ). Dankeschön :thumb: Six |
Re: Sound ausgabe 40 mal in der Sekunde
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
Zitat:
Wie genau geht denn die nichtssagende Fehlermeldung, evtl. Exception-Klasse, wo tritt er auf? Zitat:
Zitat:
Nach der Verarbeitung benötigst du zur weiteren Verarbeitung oder zur Wiedergabe wieder den Anfangswert. Entweder du stellst den Wert durch Rechnugng wieder her (dec(Data, AnzahlDerElementeDieDerZeigerZurueckgesetztWerdenS oll)) oder du änderst ihn gar nicht, sondern nutzt zwischendurch einen "Hilfszeiger". Das besondere ist eben die Arbeit mit Zeigern. Ein Zeiger speichert eine Adresse im RAM, er zeigt sozusagen auf diese Speicheradresse. Wenn du zwei Zeiger hast, die auf die gleiche Adresse zeigen, und den Wert, auf dem einer der beiden Zeiger zeigt, änderst, ändert sich der Wert an dieser Speicheradresse und somit auch der Wert an der Adresse, auf die der andere Zeiger zeigt. Eine gute Einführung zu Zeigern gibt es hier: ![]() Mfg FAlter PS: Ich habe 'ne neue Version der SOUND.dll herausgebracht. Ein großer Teil der AVs trewten jetzt nicht mehr aus. //edit: Oh mann, es gibt ja wirklich 'nen User "RAM". Ich meine hier den Random Access Memory. |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Zitat:
Wo wird denn mitgeteilt, wie die erzeugte datei Aussehen soll und das sie zwei Spuren hat? Bist du dir sicher, dass es wirklich mit dem Code funktionieren sollte? PS: Danke für den Link und die Datei! Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Sieht so aus, als ob du das WaveFormat vom MONO-Sound genommen hast. Bei Stereo musst du ein neues WaveFormat nehmen. Du solltest dieselben Daten nehmen bei meiner Funktion zum PCM-Wave-Format-Erstellen, außer, dass bei Channels nicht 1 sondern 2 steht. Mfg FAlter |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Also muss ich "Ziel" irgendwie erst als Stereosound deklarieren? Aber wie?
Delphi-Quellcode:
So gehts ja nicht, weil ich ja keine Sounddatei erzeugen möchte... was meinst du also?
FormatStereo := PCMWaveFormat(2 {Stereo}, 16 {Bits}, 44100 {Hz Samplerate});
Ziel := CreatePCMRectMemory(22000, 1000, @FormatStereo, @Size); Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Dein Code: Zitat:
Delphi-Quellcode:
Also nur ein anderes WaveFormat nehmen, den Stereosound hast du ja bereits als ein solcher erstellt.
Quelle1:=Data; // erster Monosound
Quelle2:=Data3; //zweiter Monosound GetMem(ziel, 2*size); for i := (Size div 2) - 2 downto 0 do //div 2 wegen 16 Bit = 2 Bytes begin ziel^ := quelle1^; inc(Ziel); ziel^ := quelle2^; inc(Ziel); // <-- edit: ergänzt, fehlte end; //Änderung FormatStereo := PCMWaveFormat(2 {Stereo}, 16 {Bits}, 44100 {Hz Samplerate}); //Änderung ende SavePCMMemoryToFile(Ziel, 'C:\Result.wav', {Änderung}FormatStereo{Änderung Ende}, Size); //Abspeichern Mfg FAlter |
Re: Sound ausgabe 40 mal in der Sekunde
Ohhhh, ja, wie dumm von mir :wall: :wall: :wall:
Danke vielmals Falter :thumb: Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hi Falter,
Es funktioniert leider immer noch nicht. Die Exception, die ich bekomme ist übrigens eine Zugriffsverletzung. Ich bin hier langsam echt am verzweifeln :? Wo liegt der Fehler? Six |
Re: Sound ausgabe 40 mal in der Sekunde
So genau hatte ich mir deinen Code gar niocht angesehen, du hattest noch einen Fehler drin:
Delphi-Quellcode:
Du musst den Pointer auf den Anfang deiner Daten übergeben, du übergibst aber einen Pointer auf das Ende!
GetMem(Ziel, ...)
for... begin ... inc(Ziel); end; SavePCMMemoryToFile(Ziel, ...); FALSCH:
Delphi-Quellcode:
RICHTIG:
GetMem(Data);
inc(Data); SavePCMMemoryToFile(Data);
Delphi-Quellcode:
Also genau das, wo du gestern gefragt hast, warum man es machen muss, hast du vergessen.
GetMem(Data);
Data2 := Data; inc(Data2); SavePCMMemoryToFile(Data); |
Re: Sound ausgabe 40 mal in der Sekunde
Hi Falter,
ich habe diese Möglichkeit auch breits ausprobiert, nur was dabei rumkommt, ist zwar eine Stereodatei, die jedoch nur halb so lang ist wie das Ausgangsmaterial und einen "verkrüppelten" Inhalt hat. Also mein Code sieht dann mittlerweile so aus:
Delphi-Quellcode:
Was um alles in der Welt läuft hier bloß schief :gruebel:
GetMem(Ziel, Size*2);
Ziel2:=Ziel; for i := (Size div 2) -1 downto 0 do // Warum wird hier eigentlich nach unten gezählt? begin ziel^ := Data^; inc(Ziel2); ziel^ := Data3^; inc(Ziel2); end; SavePCMMemoryToFile(Ziel, 'C:\Result.wav', FormatStereo, Size); Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hi,
Du solltest deinen Code vor dem Posten nochmal genau ansehen. Dann findest du solche Fehler bestimmt selbst.
Delphi-Quellcode:
Zum nach unten Zählen: Wenn du die Codeoptimierung an hast, würde der Compiler eh den Code für nach unten zählen generieren, weil es schneller ist, mit null zu Vergleichen, als mit was-auch-immer-bei-der-Berechnung-rauskommt.
ziel2^ := Data^;
inc(Ziel2); ziel2^ := Data3^; inc(Ziel2); In diesem Fall ist die Zählrichtung egal. Mfg FAlter |
Re: Sound ausgabe 40 mal in der Sekunde
Hi Falter,
Stimmt, hatte ich übersehen :oops: Leider ist die erzeugte Datei einfach Leer (die anderen beiden Dateien werden richtig erstellt!) Mit "Leer" meine ich, es wird eine Stereodatei erstellt, die die richtige Länge hat (Size*2), jedoch keine Informationen enthält.
Delphi-Quellcode:
Hmmm, woran könnte es denn noch liegen :gruebel:
GetMem(Ziel, Size*2);
Ziel2:=Ziel; for i := (Size div 2) -1 downto 0 do begin ziel2^ := Data^; inc(Ziel2); ziel2^ := Data3^; inc(Ziel2); end; SavePCMMemoryToFile(Ziel, 'C:\Result.wav', FormatStereo, Size*2); // *2 hinzugefügt SavePCMMemoryToFile(Data, 'C:\Test2.wav', Format, Size); // Datei Mit Signal SavePCMMemoryToFile(Data3, 'C:\Test3.wav', Format, Size); // Datei mit SinusTon Six |
Re: Sound ausgabe 40 mal in der Sekunde
Hier die entscheidende Stelle, für jeden, der es eventuell noch brauchen kann:
Delphi-Quellcode:
Nochmals vielen Dank an Falter!
GetMem(Ziel, Size * 2);
Ziel2 := Ziel; Data2 := Data; Data4 := Data3; for i := (Size div 2) - 1 downto 0 do begin ziel2^ := Data2^; Inc(Ziel2); inc(Data2); ziel2^ := Data4^; Inc(Ziel2); inc(Data4); end; Six |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz