Seite 1 von 1

IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 14:12
von DarkSoul
Hallo Forum,

ich habe versucht, einen IMA-ADPCM-Decoder zusammenzuschustern. Leider klappt das ganze nicht so, wie ich mir das vorstelle. Die Musik ist deutlich erkennbar, allerdings schwimmt die Lautstärke und ca. jede Sekunde ist ein Klickgeräusch zu hören. Die Tonschwingungen in Audacity betrachtet "torkeln" auch ziemlich und clippen an einigen Stellen. Also der Weg ist irgendwie richtig.

Achtung: Quick'n'Dirty (besonders das mit den Array-String-Zeug am Anfang und wie ich den WAV-Header "verarbeite") und ein wenig verbastelt durch meine Fehlersuche. So, wie er jetzt gerade ist. Es muss erstmal laufen. Verbessern kann man dann immer noch.

Die Daten können am Ende ohnehin headerless bleiben. Es ist ganz genau festgelegt, wie die IMA-ADPCM Dateien zu sein haben.

Zunächst 4Bit/11025Hz/Mono zum Testen.

Die Quelldaten liegen im RAW-Format vor (mit FFMPEG codiert). Hatte zuerst .WAV. Wollte ausschließen, dass es am Container liegt. Darum war ich auf RAW umgestiegen.

Für diesen einen Zweck möchte ich keine fette Lib nutzen, weil das Programm selbst eine DLL wird und ich die nicht von externen Dateien abhängig machen möchte.

Ich denke, es ist ein kleiner Fehler.

Ich muss zu meiner Schande gestehen, dass ich das aus einem meiner anderen Projekte hergenommen habe. Jedoch habe ich damals dieses andere Projekt in C geschrieben und ich versuche, dasselbe in PB zu erreichen. Ich hab das schon zig male abgeglichen und ich finde den Fehler nicht.

Das Portieren von C nach PB geht mir irgendwie immer nach hinten los... Da fluche ich jedes Mal :mrgreen:

PB finde ich persönlich schwieriger als C. Dafür gehts oft schneller, wenn es um so Kleinkram geht.

Code: Alles auswählen

Procedure DecodeADPCM(file.s)
  ;sorry dafür. Ich habe das PB-Gegenstück zu [1,2,3,4...] nicht gefunden. Sollte aber nicht die Ursache sein, weil die Arrays stimmen
#ima_step_table="7,8,9,10,11,12,13,14,  16,17,19,21,23,25,28,31, 34,37,41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,173,190,209,230, 253,279,307,337,371,408,449, 494,544,598,658,724 ,796,876,963,1060 ,1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327,3660,4026 ,4428,4871,5358, 5894,6484,7132,7845,8630,9493, 10442,11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794, 32767"
  #ima_index_table="-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8"
  
  Dim imaStepTable(89)
  For a = 0 To 88
    imaStepTable(a) = Val(StringField(#ima_step_table, a + 1, ","))
    Debug imaStepTable(a)
  Next a
  
  Dim imaIndexTable(16)
  For a = 0 To 15
    imaIndexTable(a) = Val(StringField(#ima_index_table, a + 1, ","))
  Next a
  
  If ReadFile(0,file) ;raw-Datei öffnen
    OpenFile(1,file + ".pcm.wav") ;Debug-Ausgabe-Datei öffnen (ist eine raw! .wav steht da nur, damit Audacity die leichter aufkriegt)
    ;string.s
    ;Repeat
    ;  string + Chr(ReadAsciiCharacter(0))
    ;  If Len(string) > 4
    ;    string = Right(string,4)
    ;  EndIf
    ;  ;Debug string
    ;Until Eof(0) Or string = "data"
    ReadByte(0) ;zwei crappy bytes am Anfang, die für Glitches sorgen? Liegt hier das Geheimnis begraben?
    ReadByte(0)

   ;decoder
    Dim n(2) 
    diff = 0
    stp = 0
    index = 0
    pred = 0
    While Eof(0) = 0
      a = ReadByte(0)
      n(0) = a & $0f  ;geht sicher einfacher, ein .b auf zwei nibble aufzuspalten
      n(1) = (a & $f0) >> 4
      For i = 0 To 1
        
        code = n(i) & $0f ;dirty conversion signed->unsigned. Wie geht das in PB? xD

        stp = imaStepTable(index)
        
        diff = stp >> 3
        If ((code & 4) <> 0) : diff + stp : EndIf
        If ((code & 2) <> 0) : diff + (stp >> 1) : EndIf
        If ((code & 1) <> 0) : diff + (stp >> 2) : EndIf
        If ((code & 8) <> 0) : diff = 0-diff : EndIf

        pred + diff
        If (pred > 32767) : pred = 32767 : EndIf    ;hard-limiter
        If (pred < -32768) : pred = -32768 : EndIf

        index + imaIndexTable(code);
        If (index < 0) : index = 0 : EndIf
        If (index > 88) : index = 88 : EndIf

        WriteByte(1, pred / 256)  ;conversion auf 8bit mono
        
        
        
      Next i
    Wend
    CloseFile(1)
    CloseFile(0)
  EndIf  
EndProcedure

DecodeADPCM("adpcm.raw")
Eine .PBI oder eine Fertig-Methode würde mir auch reichen. Ich konnte über Google nichts finden.

Alternativ kann ich auch MS-ADPCM verwenden.

Hauptsache, das funktioniert. Decodieren reicht aus.

Dass er in eine Datei decodiert, ist nur zum Testen, damit ich mit Audacity reingucken kann. Am Ende soll mit richtigem Header usw. in den Speicher hineindecodiert werden und dann mit PlaySound() oder was auch immer abgespielt werden.

Vielleicht kann hier jemand helfen. 8)

Eine adpcm.raw kann ich bei Bedarf nachliefern.

Compiler:Windows, 5.31, 32Bit

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 15:09
von ts-soft
Du solltest in der dritten Zeile des Codes, Datazeile, mal ein paar Leerzeichen einfügen, ansonsten wird es schwierig Deinen Beitrag zu
lesen, da das Forum nicht umbrechen kann.

Danke,
Thomas

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 16:37
von DarkSoul
Das sollte so richtig sein. Die nachfolgenden Zeilen parsen ja den String als Zahlenwerte in das Array. Das Einfügen von Leerzeichen würde zu noch mehr Fehlern führen.
Das Array stimmt am Ende. Das habe ich bereits überprüft.

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 17:26
von ts-soft
Es geht nicht um die Richtigkeit des Codes, der bleibt ja erhalten, es geht um das Umbrechen des Textes im Forum. Ich werde auf jeden
Fall nicht Stundenlang nach rechts scrollen, um etwas Lesen zu können /:->

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 19:36
von DarkSoul
Hä? Was meinst du genau?

Bei mir wird der Source Code richtig angezeigt.

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 19:50
von ts-soft
Der SourceCode wird ja richtig angezeigt, aber es wird nicht umgebrochen, und das gilt für Deinen gesamten Text!
Statt:

Code: Alles auswählen

#ima_step_table="7,8,9,10,...
mal:

Code: Alles auswählen

#ima_step_table="7, 8,  9,  10, ...
musst ja nicht hinter jedem komma ein Leerzeichen einfügen, aber ab und zu!

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 20:08
von DarkSoul
Meinst du so, wie es jetzt ist?

Irgendwie ist die Einrückung jetzt ein bisschen kaputt. Das bekomme ich nicht anders hin. :|

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 20:46
von ts-soft
DarkSoul hat geschrieben:Meinst du so, wie es jetzt ist?
Genau!
DarkSoul hat geschrieben:Irgendwie ist die Einrückung jetzt ein bisschen kaputt. Das bekomme ich nicht anders hin. :|
Da ist nichts kaputt, mit Copy und Paste und alles ist normal formatiert in der IDE :D

Aber das wichtigste, Du brauchst nicht mehr nach rechts scrollen um Deinen Text zu lesen! So findet sich auch schneller,
jemand der Hilft. Ich bin da für Sound nicht so der Richtige.

Gruß
Thomas

Re: IMA ADPCM-Decoder funktioniert nicht

Verfasst: 19.06.2016 23:43
von DarkSoul
Habe es nun doch noch hinbekommen.

Im Code hätte man noch lange suchen können... Das aktuelle FFMPEG erzeugt nämlich fehlerhafte Raw-ADPCM-Dateien. :freak: :freak: Ich habe mich darauf verlassen, dass der Encoder bewährt und bugfrei ist.

Wenn ich nämlich die Vorversion benutze und das Ergebnis an meinen Decoder verfüttere, funktionierts bestens. :allright:

Habe den Code nun nochmal ins reine geschrieben und mir ein .pbi von basteln können.

Trotzdem Danke.


Falls es wen interessiert, wieso ich es haben wollte:
Ich wollte Gamesound haben, wie er früher war (mono, 22050Hz ADPCM). Aus diesem Grunde habe ich dem Ding zusätzlich noch einen billigen Nearest-Neighbour-Resampler gebastelt, der der Soundkarte ein wenig Arbeit abnimmt. :bounce:
Da konnte ich mit .ogg nicht so viel anfangen. :roll: