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
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")
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.
Eine adpcm.raw kann ich bei Bedarf nachliefern.
Compiler:Windows, 5.31, 32Bit