Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Audio programmiertechnisch in Lautstärke & Tonhöhe verändern (https://www.delphipraxis.net/86550-audio-programmiertechnisch-lautstaerke-tonhoehe-veraendern.html)

St. Janos 15. Feb 2007 15:07


Audio programmiertechnisch in Lautstärke & Tonhöhe verän
 
ahoi,
Vorwort:
ich habe vor ein Programm zu schreiben, mit welchem man innerhalb einer Audio-Datei ab einer vorbestimmten Position für eine bestimmte Zeitspanne (sollte möglich sein als minimal wie auch sehr gross definiert zu werden) die Lautstärke zu verringer oder anzuheben (wieder von minimal bis sehr stark) oder die Tonhöhe zu verringer bzw. anzuheben (auch wieder von minimal bis sehr stark). Oder beides. Nach der Veränderung sollte es möglich sein, die veränderte Audio-Datei abzuspeichern. So das die Änderungen in der abgespeicherten Version "hart-kodiert" sind bzw. fest verankert sind. Also nicht via Tag-Information.

Da ich noch ganz am Anfang meines Projektes stehe, stellt sich mir vorerst einmal die Frage: Welche Programmiersprache und auch welches Audioformat sich für mein Vorhaben am besten eignet.
Bzgl. der Audioformate bin ich recht frei in der Wahl. Wer da also eins empfehlen kann, egal welches, immer nur raus damit:D
In sachen Programmiersprachen würde ich natürlich gerne eine Sprache nutzen, in der ich mich bereits grundlegend auskenne.
Favorisiert wären deshalb: C, Objekt Pascal (Delphi 7) oder Java
Da ich mich jedoch noch nie mit der programmiertechnischen Seite der Audioverarbeitung wie .bearbeitung befasst habe, würde ich bei triftigen Gründen mich auch in eine neue Programmiersprache einfinden wollen ;)

Die Frage:
Worum ich Euch nun bitten würde, mir hier vielleicht einmal Eure Empfehlungen nieder zu schreiben. Gerne auch mit der ein oder anderen Begründung oder Verweisen zu Informationsquellen bzgl. Audioverarbeitung mit jeglicher Programmiersprache.
Wenn jmd. hat, wuerde ich mich auch sehr über Quellcoden zu dem Thema freuen, mit dem ich ein wenig rumexperimentieren kann ;)
Ich freue mich auf Antwort.

Grüße

Janos

shmia 15. Feb 2007 16:41

Re: Audio programmiertechnisch in Lautstärke & Tonhöhe v
 
So ein Programm muss man ganz klar in Delphi :love: schreiben.
Als Audioformat kommt vorallem das Wav-Format mit 16 Bit in Frage.
Die Daten sollten im Speicher als 16 Bit signed Integer vorliegen, damit du diese mit einem Faktor multiplizieren kannst.
Lautstärkeänderung sind recht einfach zu erreichen (da jeder Samplewert einfach mit einem Faktor multipliziert wird.)
Tonhöhenänderungen sind da schon deutlich anspruchsvoller.
Wenn schon, dann sollten die Lautstärkeänderung über ein Profil oder Verlauf vorgegeben werden.
z.B. über eine Datei: 100%, 80%, 60%, 50%, 20%, 70%

St. Janos 16. Feb 2007 17:37

Re: Audio programmiertechnisch in Lautstärke & Tonhöhe v
 
ahoi,
nachdem ich nun einige Stunden Beispiel-Quellcode der Bass.dll Doku wie die Doku selber studiert habe, hät ich erstmal 1-2 grundlegende Fragen:
Und zwa geht es um die Procedure DecodeFile aus dem writewav Beispiel.

Hier einmal die Procedure:

Delphi-Quellcode:
procedure TForm1.DecodeFile(OutPath, SourceFileName : String);
 var chan, frq, vl : DWORD; Tmp: Integer;
     buf : array [0..10000] of BYTE;
   BytesRead : integer;
   temp : string;
   i : longint;
   RecStream : TFileStream;
   nChannels      : Word;  // number of channels (i.e. mono, stereo, etc.)
   nSamplesPerSec : DWORD; // sample rate
   nAvgBytesPerSec : DWORD;
   nBlockAlign    : Word;
   wBitsPerSample : Word;  // number of bits per sample of mono data
   FileName : String;
   chaninfo: BASS_CHANNELINFO;
begin

    chan := BASS_StreamCreateFile(FALSE, PChar(SourceFileName), 0, 0, BASS_STREAM_DECODE);

    CancelOp := False;
    LabelOp.Caption     := 'Opening file ...';

  BASS_ChannelGetInfo(chan, chaninfo);
   nChannels := chaninfo.chans;
        if (chaninfo.flags and BASS_SAMPLE_8BITS > 0) then wBitsPerSample := 8 else wBitsPerSample := 16;
   nBlockAlign := nChannels * wBitsPerSample div 8;
   BASS_ChannelGetAttributes(chan, frq, vl, Tmp);
        nSamplesPerSec := frq;
   nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;

    FileName := ExtractFileName(SourceFileName);
    FileName := Copy(FileName, 1, Length(FileName) - Length(ExtractFileExt(FileName)));
    RecStream := TFileStream.Create(OutPath + FileName + '.wav', fmCreate);

 // Write header portion of wave file
    temp := 'RIFF'; RecStream.write(temp[1], length(temp));
    temp := #0#0#0#0; RecStream.write(temp[1], length(temp));  // File size: to be updated
    temp := 'WAVE'; RecStream.write(temp[1], length(temp));
    temp := 'fmt '; RecStream.write(temp[1], length(temp));
    temp := #$10#0#0#0; RecStream.write(temp[1], length(temp)); // Fixed
    temp := #1#0; RecStream.write(temp[1], length(temp));      // PCM format
    if nChannels = 1 then
       temp := #1#0
    else
       temp := #2#0;
    RecStream.write(temp[1], length(temp));
    RecStream.write(nSamplesPerSec, 2);
    temp := #0#0; RecStream.write(temp[1], length(temp));  // SampleRate is given as dWord
    RecStream.write(nAvgBytesPerSec, 4);
    RecStream.write(nBlockAlign, 2);
    RecStream.write(wBitsPerSample, 2);
    temp := 'data'; RecStream.write(temp[1],length(temp));
    temp := #0#0#0#0; RecStream.write(temp[1],length(temp)); // Data size: to be updated
   while (BASS_ChannelIsActive(chan) > 0) do
         begin
                BytesRead := BASS_ChannelGetData(chan, @buf, 10000);
                RecStream.Write(buf, BytesRead);
                Application.ProcessMessages;
                if CancelOp then Break;
                PercentDone := Trunc(100 * (BASS_ChannelGetPosition(Chan) / BASS_ChannelGetLength(chan)));
                ProgressBar.Position := PercentDone;
                LabelOp.Caption     := 'Done ' + IntToStr(PercentDone) + '%';
   end;
   BASS_StreamFree(chan); // free the stream

   LabelOp.Caption     := 'Closing file ...';
// complete WAV header
// Rewrite some fields of header
   i := RecStream.Size - 8;   // size of file
   RecStream.Position := 4;
   RecStream.write(i, 4);
   i := i - $24;              // size of data
   RecStream.Position := 40;
   RecStream.write(i, 4);
   RecStream.Free;
   LabelOp.Caption     := 'Done';
end;
Wie die Procedure funktioniert und was Sie macht, is mir glaub ich klar. Nachdem ich nun auch ausführlich den Wav-Header studiert habe, stellen sich mir jedoch 2 grundlegende Fragen, die wohl mehr mit dem Delphi Syntax zu tun haben. Wessen Schreibweise ich mich nicht wirklich erinnern kann, so schon mal gesehen zu haben. Bis auf glaube ich bei RGB-Farb-Code Zuweisungen. Naja, ich schweife ab ;)
Es geht um die Zeilen:

Delphi-Quellcode:
    temp := #$10#0#0#0; RecStream.write(temp[1], length(temp)); // Fixed
    temp := #1#0; RecStream.write(temp[1], length(temp));      // PCM format
wie um
Delphi-Quellcode:
i := i - $24;              // size of data
Mir ist klar, dass im oberen Teil nur Platzhalter eingetragen werden. Jedoch verstehe ich nicht welche Bedeutung in Delphi diese Zeichenkombinationen haben, wenn Sie ohne Hochkommatas zugewiesen werden.
Also was bewirkt zb. #1#0 oder #$10#0#0#0 oder auch x - $24 wenn x jetzt mal 100 sei?
Leider hab ich es net hinbekommen nach solchen Zeichenkombinationen gescheit zu suchen und hoffe deshalb auf Eure Hilfe.
Eine 2. Sache dich mich stutzig macht ist, dass in der letzteren von mir erwähnten Zeile die Stream/Dateigrösse mit 24 subtrahiert wird. Laut Wikipedia werden bis einschließlich der fmt-Header Länge erst 20 Bytes verbraucht. Was auch immer $24 zu bedeuten hat, müsste es nicht $20 heißen? Meine Vermutung wird mit aller Wahrscheinlichkeit falsch sein, aber warum $24 und nicht $20? Mir würde sehr geholfen werden, wenn Ihr mir auch diese Frage beantworten könntet ;)

Außerdem frag ich mich, wie du des meinst mit dem multiplizieren der Daten? Was genau multiplizieren? Und mit was und was für eine Verstärkung der Lautstärke bewirkt die Mulitplikation mit dem Faktor x bzw. mit welchem Faktor erreich ich die minimalste Verstärkung/Verringerung der Lautstärke? Und was wäre die minimalste Verstärkung/Verringerung in dB oder auch %? Ich weiss, viele Frage auf einmal. Aber in Sachen Veränderung seh ich noch kein Licht am Ende des Tunnels:P

Grüße Janos

Ps.: Anbei habe ich mich inzwischen entschieden, dass Projekt mit Delphi und Wave-Dateien oder Mp3-Dateien oder OGG-Dateien fortzuführen :)

shmia 16. Feb 2007 18:08

Re: Audio programmiertechnisch in Lautstärke & Tonhöhe v
 
Zitat:

Zitat von St. Janos
Delphi-Quellcode:
    temp := #$10#0#0#0; RecStream.write(temp[1], length(temp)); // Fixed
    temp := #1#0; RecStream.write(temp[1], length(temp));      // PCM format
wie um
Delphi-Quellcode:
i := i - $24;              // size of data
Mir ist klar, dass im oberen Teil nur Platzhalter eingetragen werden. Jedoch verstehe ich nicht welche Bedeutung in Delphi diese Zeichenkombinationen haben, wenn Sie ohne Hochkommatas zugewiesen werden.

Das Dollarzeichen ($) vor einer Zahl bedeutet, dass diese hexadezimal zu interpretieren ist.
Der Gartenzaum (#) bedeutet, das die folgende Zahl der Wert des Zeichens ist:
Delphi-Quellcode:
temp := #$10#0#0#0;
temp := chr(16)+chr(0)+chr(0)+chr(0); // das ist das Gleiche wie oben, nur viel umständlicher
Zitat:

Zitat von St. Janos
Außerdem frag ich mich, wie du des meinst mit dem multiplizieren der Daten? Was genau multiplizieren? Und mit was und was für eine Verstärkung der Lautstärke bewirkt die Mulitplikation mit dem Faktor x bzw. mit welchem Faktor erreich ich die minimalste Verstärkung/Verringerung der Lautstärke?

Erst mal musst du verstehen, wie Signale digital dargestellt werden.
http://de.wikipedia.org/wiki/Bild:PAM-Prinzip.png
Jeder blaue Strich in dem Bild stellt einen digitalisierten Wert im Bereich von -128 bis +127 (bei 8-Bit Auflösung) dar.
Wenn du jetzt jeden einzelnen Wert mit 0.5 multiplizierst, dann ist das Signal halb so laut.
Wenn du mit Werten grösser 1.0 multiplizierst, wird das Signal lauter.
Aber Vorsicht: zu viel, und der gültige Wertebereich wird verlassen, was ganz grausame Verzerrungen verursacht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:03 Uhr.

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