ffmpeg decode audio

  • Ich versuche schon seit längerer Zeit mit dem ffmpeg decoder ein Programm zu schreiben das mit den Audiostream analysiert,
    Ich komme da nicht wirklich weiter.
    In der mailinglist bekomme ich leider immer nur gesagt: "so und so müsste es gehen"
    Beispiele habe ich, nach langem suchen, zwar gefunden, aber die machen leider alle was anderes.


    Also zu meinem Problem:
    Ich kann zwar ein AudioFrame auslesen und decodieren.
    In dem Frame sind dann so ca 1152 AudioSamples drinnen.
    Über 4800 Samples (ca 0.1sec) will ich dann den mittelwert der Lautstärke ermitteln.
    Die Lautstärke ist dabei die Summe der Quadrate.
    Leider finde ich keine Angabe ob ich die 16bit nun noch swappen muss oder nicht.
    Ich weiß auch nicht ob die beiden Channels immer im wechsel nacheinander kommen.
    Ich habe in der mailingslist einen Tip bekommen das ich immer 32768 abziehen muss.
    Das ist wohl der offset. Bin mir da aber nicht sicher.


    Anbei ein Auszug aus meinem Code.
    Ich hoffe echt das es hier jemanden gibt der sich mit sowas auskennt.
    Leider gibt es kein ffmpeg Forum und in anderen c++ Foren bekomme ich keine Antwort.


    Der Code gibt mir zwar einen Wert, jedoch entspricht das nicht der Lautstärke.
    Ich habe ein TestVideo in dem die Lautstärke immer lauter wird.
    Mein Code zeigt mir davon jedoch nichts an.

  • ich kann dir auch einen Tip geben, schau dir mal softdevice an ;)


    ansonsten würde ich einfach mal den Buffer "src" in eine Datei schreiben und schaun, ob du überhaupt was brachbares dekodierst, indem du versuchst das File dann mit einem RAW-Player (man aplay) abzuspielen. Das mit den 32768 könnte hin kommen, aber auch die definitin von chan1/2 (uint16 bzw int16)


    Gruß
    Roland

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • Hi,


    geh doch mal nach www.wotsit.org. Dort findest du bestimmt etwas zum Format der Files.
    Wenn du mit ffmpeg nach 'raw' CD-Audio extrahierst, dann bekommst du doch sowas wie: 2Byte Kanal1, 2Byte Kanal2, wieder 2Byte Kanal1, usw., oder?
    Swappen musst du die Bytes glaube ich nicht. Dem 16-bit Maximalwert 0xFFFF ist eine 'Nulllinie' bei 0x8000 zugeordnet. Alles darunter ist negativ, darueber positiv. Findest du aber bei wotsit.


    Der Tipp von Roland ist auch nicht schlecht, einfach einen CD-Header bauen (siehe wotsit), dann deine 'raw'-Daten dazu packen und du bekommst wohl ein .wav. Das kannste ja dann bequem abspielen.


    Wenn du was hast, lass es mich doch bitte wissen. Ich will naemlich auch aus einigen guten Konzertaufnahmen den Sound extrahieren und eine Audio-CD daraus bauen. Wenn das alles nur mit ffmpeg ginge waere das ja klasse


    Gruss,
    - berndl

  • nochmal ich, ich habe da noch was aus alten OS/2-Tagen gefunden:



    Die 'xxxx' sind genau so im WAV rein kodiert, nach diesem Header kommen die Daten, und zwar als (SHORT)links, (SHORT)rechts, (SHORT)links, usw.


    hth,
    - berndl

  • Ihr glaubt ganicht wie Froh ich bin das jemand geantwortet hat :)


    Zitat

    Original von pram
    ich kann dir auch einen Tip geben, schau dir mal softdevice an ;)


    Leider habe ich da nichts gefunden was mir bei meinem Problem helfen könnte :(

    Zitat

    Original von pram
    ansonsten würde ich einfach mal den Buffer "src" in eine Datei schreiben und schaun, ob du überhaupt was brachbares dekodierst, indem du versuchst das File dann mit einem RAW-Player (man aplay) abzuspielen.


    Habe ich gemacht.
    Ist schon sehr witzig. Nun habe ich ein Programm mit dem ich fast alle Formate nach wav convertieren kann :)

    Zitat

    Original von pram
    Das mit den 32768 könnte hin kommen, aber auch die definitin von chan1/2 (uint16 bzw int16)


    Was meinst Du nun damit?


    berndl
    Das schreiben des Headers habe ich mir erspart.
    Kann man bei aplay als param übergeben.


    Also richtig decodiert wird wohl.
    Nur das mit dem Berechnen der Power haut nicht hin.
    Oder ich interpretiere das Ergebniss falsch.


    In meinem Testfile wird ein Ton immer lauter.
    Mein Programm sagt mir aber:


    Die Power in dem Zeitfenster: 21 betraegt:83953104
    Die Power in dem Zeitfenster: 42 betraegt:79447583
    Die Power in dem Zeitfenster: 63 betraegt:63954875
    Die Power in dem Zeitfenster: 84 betraegt:60982776
    Die Power in dem Zeitfenster: 105 betraegt:61148841
    Die Power in dem Zeitfenster: 126 betraegt:66726547
    Die Power in dem Zeitfenster: 146 betraegt:77666794
    Die Power in dem Zeitfenster: 167 betraegt:70286323


    Stimmt den was mit meiner Formel nicht?
    Ich habe sie von
    http://cnx.rice.edu/content/m10055/latest/


    Zz messe ich die Power über 24000 Samples. Das entspricht bei 48k genau 0.5 sec.


    berndl
    Soll ich dir den Code jetzt schon schicken?
    Hier ist der wichtige Auszug:


  • Der Fehler liegt meiner Meinung irgendwo in diesen 4 Zeilen:

    Code
    chan1 = *((int16_t *)src);
                    chan2 = *((int16_t *)(src+2));                
                    power = ((chan1-0x8000)*(chan1-0x8000) + (chan2-0x8000)*(chan2-0x8000)) / 2;                
                    avg = (avg * c + power ) / (c+1);


    Das zuerst 2byte linker Kanal und 2byte rechter Kanal kommt, das sollte in Ordnung sein.
    Mögliche Fehlerquellen sind deshalb nur noch die Konvertierung in int:
    ich würde mal folgendes probieren:


    int chan1 = *((uint16_t *)src) - 0x8000; // man beachte int und uint16_t
    int chan2 = *((uint16_t *)src) - 0x8000;
    int power = (chan1*chan1) + (chan2*chan2);
    int avg = (avg * c + power) / (c+1);
    printf("%d\t%d\t%d\t%d\n", chan1, chan2, power, avg);


    --
    Nachtrag: Hab mir grad die Sourcen von Noad angesehen und die sehen deinem Code sehr ähnlich (bswap fehlt), deshalb vermute ich mal dass es zu einem Überlauf kommt, wenn du auf "power" umrechnest:
    power = (((int)chan1-0x8000)*((int)chan1-0x8000) + ((int)chan2-0x8000)*((int)chan2-0x8000)) / 2;
    könnte helfen.


    Das ganze dann in ein Textfile dumpen und mit Openoffice/gnuplot oder Excel ein Diagramm erstellen, dann sollte sich leicht klären lassen, wo und ob man noch 0x8000 abziehen bzw. die bytes geswappt werden sollten


    Gruß
    Roland

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

    Einmal editiert, zuletzt von pram ()

  • Hi Leute,


    könnte das Ganze etwa in einem grafischen Equalizer (insb. interessant für Olaf) münden bzw. zu einem umgebaut werden? Du bekommst ja die Lautstärke dann schon berechnet - das müsste man sozusagen dann "nur noch" pro Frequenzanteil machen. Aber wahrscheinlich geht gerade meine Phantasie mit mir durch ...


    Viele Grüsse
    Chriss

  • theonlychriss
    Da muß ich dich leider entteuschen. Habe damit nichts zu tun.


    pram
    Du hast recht es muss was mit den Zeilen zu tun haben.
    Ist so ein "unsigned->signed; 8->16 bit; überlauf " kram.
    Das ist wieder eine schwachstelle von C :(


    Ich habe mir mal die Werte von Chan1 und 2 genauer angesehen.
    Die sind manchmal auch negativ (zwar nur gering max -4) aber das bedeutet im Grunde dann das ich nicht 0x8000 abziehen muss. (hoffe ich)


    Das der Code mit NoAd viel Ähnlichkeit hat liegt dadrann das ich mir den NoAd Code auch angesehen habe. Dazu kommt aber auch das es so ähnlich auch in der ffmpeg Doku steht.
    Man könnte also sagen das alles aus der selben Quelle kommt.
    Im Vergleich zu NoAd habe ich jedoch noch etwas mehr Code drumherum.
    NoAd prüft jedoch "nur" auf Silent.
    Ich will ja die (Lautstärke)Power haben.


    Nun scheint es zu klappen.
    Was mich aber gerade wunder ist folgende Erkenntniss:
    Sind höhere Frequenzen (bei gleicher Amplitude) lauter als tiefe Frequenzen?

  • Zitat

    Nun scheint es zu klappen.


    freut mich

    Zitat

    Nun scheint es zu klappen.
    Was mich aber gerade wunder ist folgende Erkenntniss:
    Sind höhere Frequenzen (bei gleicher Amplitude) lauter als tiefe Frequenzen?


    Ja das Gehör hat einen nichtlinearen Frequenzgang, siehe http://de.wikipedia.org/wiki/Lautheit


    Was mir an deinem code aber noch nicht gefällt ist dass du avg immer auf 0 setzt.
    (die avg = ... Zeile bewirkt lediglich eine Tiefpassfilterung)
    In deinem Fall werden nämlich Samples die am Schluss vom 0,5 sek -Fenster stärker gewichtet.


    ich würd entweder ein dementsprechend großes 'c' nehmen und avg nicht auf 0 setzen oder alle Power-Werte summieren und dann durch 24000 teilen.


    Gruß
    Roland


    p.S. darf ich fragen was das wird?

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • So nun habe ich es getestet und alles geht.
    Da es doch etwas mehr code geworde ist(170 Zeilen), poste ich hier nur die wichtigsten Zeilen.


    Nun werde ich alles wieder wegschmeissen und mich meinem eigentlichen Programm zuwenden.
    Wenn jemand den ganzen code von diesem Beispielprogramm haben möchte, dann soll er mir eine PN schicken.


    Nochmal danke an alle!!


  • Zitat

    Originally posted by decembersoulWas mich aber gerade wunder ist folgende Erkenntniss:
    Sind höhere Frequenzen (bei gleicher Amplitude) lauter als tiefe Frequenzen?


    ich hab mich gerade mit der gewichtung von teilspektren beschäftigt, daher komme ich mal wieder mit irgendwelchem halbwissen.
    kuck dir mal die MEL scala an. http://de.wikipedia.org/wiki/Mel


    diese sakale ist so eine art nachbildung, der wichtigkeiten gewisser frequenzen für das hören (btw. erkennen).

  • das das menschliche Gehört nicht linear arbeitet ist mir klar.


    Das war aber auch nicht mein Problem.
    Ich hatte irrtümlich gedacht das
    Integral sin(2*Phi*5000)^2
    grösser ist als
    Integral sin(2*Phi*50)^2
    ist.
    Als ich es dann aber aufgeschrieben hatte war es dann klar.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!