Soundblasterprogrammierung

  • Moin,


    habe hier leider 2 kleinere Probleme mit dem Soundblaster:


    1. Ich bekomme den Autoinitmode nicht richtig zum laufen (die Beispiele die ich im Netz gefunden habe hatten auch nur den Singlemode genutzt und dann jedes mal die Karte neu Programmiert - für mich unpraktisch)


    2. Wie codiere ich Creative's 8bit zu 4 Bit ADPCM? Dazu habe ich leider auch nichts im Netz gefunden und die gängigen ADPCM Codecs arbeiten mit 16 zu 4 Bit, was dem Sound auf der Soundblaster nicht gerade zu gute kommt.


    ____________________________________________________________________________


    Hier erstmal die Unit:

    Die kann nur 8Bit, 8khz, Mono Dateien abspielen - mehr soll sie auch nicht können (evtl. mal 11-16khz wenn ADPCM läuft)

    Es gibt eine kleine Besonderheit: Der Int der Soundkarte wird auch als ~30 Ints/s Taktgeber genutzt - deshalb auch die funktion PlaySilence, damit es eben auch bei Stille noch einen Takt gibt.


    Das Problem ist: aktuell läuft alles klaglos durch, aber die Interruptroutine wird nicht aufgerufen. (auch nicht wenn ich beim IRQ +8 hinschreibe wie in einigen Beispielen)



    Und das Testprogramm:

    Es spielt ersteinmal Stille - bereits dabei sollte der Bildschirm mit der (Debug-) Meldung IRQ überflutet werden

    Als nächstes spielt es eine Datei (Test.wav - 8khz, 8Bit) einmal ab-

    Und zu guter letzt diese Datei nochmal in Dauerschleife.

    stattdessen spielts nur den 32k Puffer in Dauerschleife ab.


    Wenn bei euch die Soundkarte nicht auf 220,7,1 liegt, solltet ihr noch die

    "procedure SB_Set(Base_Addr:word;IRQ,DMA:byte);" aufrufen.


    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Läuft jetzt, +8 beim IRQ geht jetzt - warum auch immer.


    was es mit der +8 auf sich hat steht übrigens hier:

    https://en.wikibooks.org/wiki/…able_Interrupt_Controller (bei remapping)


    Bleibt noch das encodieren von Creative's 4-8Bit ADPCM...


    Edit: irgendwo ist noch ein Bug drin.

    Für die korrekte Funktion brauche ich ein "writeln(ioresult);" - einfach ein leeres if (oder result:=ioresult;) reicht nicht:


    Code
    function SB_PlayFile(F_Name:String;Continuos:boolean):boolean; var Result:word; {debug}
    begin
    writeln(ioresult);
    If SB_PlaySilence then
    begin
    assign(SB_File,F_Name);


    Ob eine Datei bereits offen ist wird durch SB_PlaySilence überprüft und offene Dateien geschlossen...


    Code
    function SB_PlaySilence:boolean;
    begin
    if SB_Run then
    begin;
    SB_FilePlaying:=false;
    FillChar(SB_Buffer^,32768,128);
    seek(SB_File,0);
    if IoResult=0 then close(SB_File);

    insgesamt verstehe ich das Verhalten nicht so recht, vor allem da ioresult eine 0 zurückliefert...


    EDIT2: Der Fehler war ganz einfach: es gab einen Pfad bei dem der Rückmeldecode von SB_PlaySilence nicht gesetzt wurde - was zum leicht zufälligen Verhalten geführt hat - hier ist der Fehler:

    Code
    function SB_PlaySilence:boolean;
     begin
      if SB_Run then
       begin;
       SB_FilePlaying:=false;
       FillChar(SB_Buffer^,32768,128);
       seek(SB_File,0);
       if IoResult=0 then close(SB_File);
     -> HIER GEHÖRT EIN SB_PlaySilence:=true HIN <-
       end


    aktueller Code:


    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

    Einmal editiert, zuletzt von Dosenware ()

  • Bleibt noch das encodieren von Creative's 4-8Bit ADPCM...

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Dosenware


    Respekt, Lob und Anerkennung.


    Leider kann ich dir da nicht viel helfen da mir das Softwarezeugs irgendwie nie so richtig interessiert hat.


    Da bin ich eher der Grob-Bräter-Motoriker :mrgreen

  • Ist kein Tool, Spielt Wavefiles über die Soundblaster ab - wird evtl. in ein Projekt intigriert.


    Um Platz zu sparen würde ich gerne den ADPCM Codec von Creative Nutzen, der kann von den Soundblasterkarten nativ decodiert werden und bietet in der 8 zu 4 Variante 50% Platzersparnis bei unmerklichem Qualitätsverlust - die wiederrum in eine höhere Samplerate investiert werden können, was dann wieder der Qualität zuträglich ist.

    Leider fehlen mir genauere Informationen darüber wie der Encoder funktioniert - besonders die Quantisierungsstufen und die Schrittweiten bräuchte ich.


    ADPCM funktioniert, stark vereinfacht, indem Werte extrapoliert werden, Bleistift:

    1...2...?

    Zwischen 1 und 2 beträgt die Differenz 1, also wird nach der 2 vermutlich eine 3 kommen - bei ADPCM wird der Unterschied zur Vorhersage gespeichert.


    siehe auch:

    ADPCM encoding and decoding - Programmer Sought

    https://www.vogons.org/viewtopic.php?t=59861 (2Bit Quantisierung klingt grausam - BTW. kennt wer das Lied? Klingt nach Theatre of Tragedy...)

    http://ww1.microchip.com/downloads/en/AppNotes/00643b.pdf (in der 16 zu 4 Variante - die mit den Soundblastern nicht funktioniert)

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Hmm,


    habe jetzt die 16 zu 4 Codierung nachgebaut (brauche aber die 8 zu 4 codierung): http://www.cs.columbia.edu/~hgs/audio/dvi/


    Es scheint schonmal Grundsätzlich zu funktionieren:


    Soundtest.ogg

    Alles läuft auf 8khz Samplingfrequenz, die beiden ADCPMs am Anfang sind per Dosbox wiedergegeben.


    Am Anfang der code von Columbia, danach der IMA ADPCM Codec (ein paar der Störungen kommen durch die Blockheader bei Wav) dann das "original" (halt auf 8khz mono runtergerechnet) und zu guter letzt nochmal Ima ADPCM per Winamp.


    was auffällt ist der starke DC-Anteil

    oben Columbia, IMA ADPCM, "Original", Ima ADPCM per Winamp


    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

    Einmal editiert, zuletzt von Dosenware ()

  • Yeah Baby, Protected Mode :D


    Unit DPMI (Protected Mode Interface)

    Das Testprogramm:

    Musste das ganze splitten... dämliche 10000 Zeichen Begrenzung... sagt einem nichtmal wieviel man drüber ist :-/


    Todo: verschiedene Sampleraten unterstützen, Voc Support einbauen (Creative 8 to 4 Bit Kompression habe ich zum laufen gebracht, muss aber hier noch eingebaut werden) und die Nachladeroutine überarbeiten damit sie schneller auf neue Dateien reagiert. <- Das passt unten auch nimmer hin...

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Unit SB_Unit - ich musste dort nur SB_CreateSoundbuffer, SB_Stop und einen Datentyp (SB_BufferPTR) anpassen

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Und weiter gehts:



    - Da mir die Verwendung der Soundkarte Probleme macht wenn ich neue Samples nachlade (entweder bringe ich dabei meinen Taktgeber durcheinander, oder die Sounds kommen verzögert, oder ähnlicher Käse) nehme ich jetzt den Interrupt 1C - dann geht halt im Zweifelsfall die Uhr (nicht die RTC) falsch.


    - Hinzugekommen ist auch eine Formaterkennung für Wave - unterstützt wird aber nur 8Bit in Mono mit 4-23khz, weil: das geht ab dem DSP2.0, sollten also alle Soundblaster können - und die Soundfiles sind eh riesig.

    VOC im Creative's 8zu4(3/2) ADPCM Codec werde ich wohl nochmal umverpacken - ich habe halt keinen Bock mich zur Laufzeit mit der Blockstruktur von Voc zu befassen



    Die Soundqualität ist den Zielsystemen 'angemessen', wobei ich da evtl. mit anderen Programmen beim Downsampling noch etwas rausholen kann, die leisen Passagen rauschen auch in Winamp sehr stark - das liegt also nicht an meinem Programm, bzw. Dosenbox.

    Man beachte auch wie schön schnell der Wechsel zwischen den Titeln jetzt geht :D


    Bei Titel 3 hört man auch weshalb es extremst wichtig ist die Stücke vor der Reduktion auf 8 bit zu normalisieren, bei dem leisen Anfang hört man sehr deutlich die Quantisierungsartefakte durch die geringe Bittiefe.

    Anders gesagt: der Anfang hört sich an wie ein Photo das auf 64 Farben reduziert wurde aussieht.


    Soundtest.ogg


    PS. und ich kann den QT nicht anhängen weil das Forum beschränkt ist... auf 10.000 Zeichen.... :-/

    Liebe Admins könnt ihr da nicht was machen damit zumindest im Programmierenbereich etwas mehr geht? Ich bin sicher da lässt sich was Hexen ;)


    PPS. Format 1 ist übrigens direkt aus dem Wav Header und steht für unkomprimiertes PCM: https://de.wikipedia.org/wiki/RIFF_WAVE


    EDIT: SB_Unit Part 1

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

    Einmal editiert, zuletzt von Dosenware ()

  • SB_Unit Part 2


    Und die neu dazugekommene Unit TImer:


    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Ach für mich isses bloß Spaß...


    Ich kombiniere grad 2 meiner Hobbies - wenn es läuft werde ich es evtl. im Forum vorstellen :D

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • Nachdem ich heute den ganzen Tag recht erfloglos versucht habe ADPCM im Autoinit laufen zu lassen (da wird nichtmal ein IRQ ausgelöst), habe ich aufgeben und einen Workaround genutzt.


    Statt Autoinit gibts für ADPCM nun den Singlemode DMA. D.h. der Spielt eine Anzahl bytes ab, Stopt dann und generiert einen Int - ich darf dann halt die Wiedergabe erneut anstoßen.

    In der Praxis Funktioniert das so:

    Code
      Case Format of
       1:SB_WriteDSP($1C);                                          {Start Playback PCM}
       2:begin;                                                     {Start Playback CADPCM4}
         SB_WriteDSP($75);SB_WriteDSP($FF);SB_WriteDSP($3F);        {Single DMA, Autoinit doesn't work}
         SB_AdpcmPlaying:=$74;                                      {for whatever reasons}
         end;

    Bei 2 starte ich die Singlemode DMA Wiedergabe (in dem Fall $75 für 4Bit ADPCM) und schiebe gleich noch die Anzahl der abzuspielenden Bytes hinterher ($3FFF = 16383 (+1) bytes)

    Der Trick ist hier: 16384 Bytes ist nur der halbe Puffer - der DMA Controller (der die Daten aus dem Speicher holt und zur Soundblaster schiebt) ist auf den vollen Puffer von 32k programmiert, sprich: Die Karte spielt nur den halben Puffer ab, stoppt und generiert einen Interupt.


    Jetzt kommt der zweite Teil des Tricks:


    Code
    procedure SB_ServiceIRQ; interrupt;                             {Interruptroutine}
     var Temp:Byte; Result,Result2:word;
     begin
      Temp := Port [SB_Base+$E];                                    {Relieve DSP}
      Port [$20] := $20;                                            {Relieve IRQ}
      if SB_IRQ >7 then Port [$A0] := $20;
      if SB_AdpcmPlaying>0 then begin;SB_WriteDSP(SB_AdpcmPlaying);SB_WriteDSP($FF);SB_WriteDSP($3F);end;

    Die Interruptroutine stößt sofort das weiterspielen an ("SB_WriteDSP(SB_AdpcmPlaying);SB_WriteDSP($FF);SB_WriteDSP($3F)") und befüllt anschließend die bereits abgespielte Hälfte des Puffers neu - damit werden die Pausenzeiten auf ein Minimum gehalten. Leider klickt es dennoch ab und zu wenn noch ein Int dazwischenfunkt.

    Die Variable SB_AdpcmPlaying dient übrigens sowohl als Flag als auch als Speicher für den Abspielbefehl - denn der unterscheidet sich je nach ADPCM Variante.


    Jetzt gibts noch einen kleinen Soundtest:



    In Audacity sieht das dann so aus:



    Auffällig sind besonders die "Gleichspannungsanteile" bei ADPCM (besonders bei 2 und 3 Bit)


    Und hier der Soundtest:

    Soundtest.ogg


    0:00-0:35 2 Bit ADPCM - gut geeignet für Explosionen, Rauschen und andere Störgeräusche...

    0:35-1:10 3 Bit ADPCM - für Sprache geeignet

    1:10-1:45 4 Bit ADPCM - schon brauchbar

    1:45-2:15 8Bit PCM 8kHz

    2:15-2:50 8Bit PCM 11kHz

    2:50-3:25 8Bit PCM 22kHz


    Wie immer, viel rauschen kommt wohl vom Downsampling und der reduktion auf 8 Bit - mal schauen was sich da noch machen lässt.


    Hier erstmal der QT

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

  • QT Teil 2:

    PS. mehr Zeichen bitte ;)

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

    Einmal editiert, zuletzt von Dosenware ()

  • Das Buch hab ich, leider in dem Fall recht unnütz - dort steht nichts über die Programmierung der Hardware selbst.


    Info's brauche ich da eigentlich keine weiter - höchstens zur konvertierung, bisher bekomme ich immer ein starkes Rauschen rein wenn ich auf 8 Bit konvertiere...

    Von allen Dingen auf Erden ist die Intelligenz am gerechtesten verteilt: Jeder glaubt, er hätte genug davon.

Jetzt mitmachen!

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