Waves unter DOS abspielen



  • Hallo,

    Ich schreib mir zurzeit eine kleine Funktionssammlung, die mir das programmieren eines DOS-Games ermöglicht (Grafik, Steuerung..usw). Jetzt bin ich dabei, die Funktionen für den Sound zu programmieren. Also suchte ich mir ein Tutorial für nen Waveplayer per Soundblaster. Es scheint alles bis auf das eigentliche abspielen zu funktionieren. Wenn ich versuche, eine Wav-Datei abzuspielen, bekomme ich nur 2 kurze Geräusche (so ein klicken) und das wars dann auch schon.
    Vielleicht kann mir ja jemand hier helfen?

    Hier der Code:

    #include<dos.h>
    #include<conio.h>
    #include<stdio.h>
    #include<malloc.h>
    
    #define DSP_RESET          0x06
    #define DSP_READ_DATA      0x0A
    #define DSP_WRITE_DATA     0x0C
    #define DSP_BUFFER_STATUS  0x0C
    #define DSP_DATA_AVAIL     0x0E
    #define DSP_START_DAC_DMA  0x14
    #define DSP_SET_TIME_CONST 0x40
    #define DSP_SET_BLOCK_SIZE 0x48
    #define DSP_SPEAKER_ON     0xD1
    #define DSP_SPEAKER_OFF    0xD3
    #define DSP_HALT_DMA       0xD0
    #define DSP_CONTINUE_DMA   0xD4
    #define DSP_GET_VERSION    0xE1
    
    #define FP_SEG(fptr) ((unsigned)((unsigned long) (fptr) >> 16))
    #define FP_OFF(fptr) ((unsigned)(fptr))
    
    struct WAVHeader{
       long RIFF;
       unsigned int Channels;
       long Frequency;
       char BitRes;
    };
    
    struct Wave{
       unsigned int Length, Frequency;
       char *Sample;
    };
    
    WAVHeader Header;
    
    int baseports[6] = { 0x220, 0x230, 0x240, 0x250, 0x260, 0x280 };
    int BASEPORT = 0;
    
    /******************************************************
     * Diese Funktion prüft, ob an dem gegebenen Port     *
     * ein Soundblaster-Chip erreichbar ist               *
     ******************************************************/
    bool CheckBaseport( int port )
    {
       outportb( port + DSP_RESET, 0x01 );
       delay( 10 );
       outportb( port + DSP_RESET, 0x00 );
       delay( 10 );
       if( inportb( port + DSP_DATA_AVAIL ) & 2 == 2 )
          if( inportb( port + DSP_READ_DATA ) == 0xAA )
             return 1;
       return 0;
    }
    
    /******************************************************
     * Diese Funktion sucht mithilfe der Funktion Check-  *
     * Baseport() den richtigen Soundblaster-Port         *
     ******************************************************/
    bool FindBaseport(void)
    {
       for( int i = 0; i < 6; i++ ){
          if( CheckBaseport( baseports[ i ] ) ){ 
             BASEPORT = baseports[ i ];
             printf( "Found Soundblaster-Baseport at 0x%x\n", BASEPORT );
             break;
          }
       }
       if( BASEPORT == 0 ){
          printf( "Couldn't find Soundblaster Baseport - press any key to exit" );
          getch();
          return 1;
       }
    }
    
    /******************************************************
     * Diese Funktion schickt einen Byte an den DSP       *
     ******************************************************/
    void WriteDSP( unsigned char value )
    {
       while( ( inportb( BASEPORT + DSP_WRITE_DATA ) & 0x80 ) == 0x80 );
       outportb( BASEPORT + DSP_WRITE_DATA, value );
    }
    
    /******************************************************
     * Diese Funktion lädt eine Wave-Datei in den         *
     * Speicher                                           *
     ******************************************************/
    bool LoadWave( char* Filename, Wave *wav )
    {
       FILE *wavfile;
       wavfile = fopen( Filename, "r" );
       if( wavfile == NULL ) return 1;
    
       fseek( wavfile, 0L, SEEK_END );
       wav->Length = ftell( wavfile ) - 48;
       fseek( wavfile, 0L, SEEK_SET );
       if( wav->Length > 64000 ) wav->Length = 64000;
    
       fread( &Header.RIFF, 4, 1, wavfile );
       fseek( wavfile, 22, SEEK_SET );
       fread( &Header.Channels, 2, 1, wavfile );
       fread( &Header.Frequency, 4, 1, wavfile );
       fseek( wavfile, 34, SEEK_SET );
       fread( &Header.BitRes, 1, 1, wavfile );
       if( Header.RIFF != 0x46464952 ){
          printf( "Bad file format\n" ); return 1;
       }
       if( Header.Channels != 1 ){
          printf( "Not a mono wave file\n" ); return 1;
       }
       if( Header.BitRes != 8 ){
          printf( "Not a 8-bit wavefile\n" ); return 1;
       } 
    
       wav->Frequency = Header.Frequency;
    
       wav->Sample = (char*)malloc( wav->Length );
       if( !wav->Sample ) return 1;
       fread( wav->Sample, wav->Length + 2, 1, wavfile );
    
       fclose( wavfile );
       return 0;
    
    }
    
    /******************************************************
     * Diese Funktion spielt eine bereits geladene WAV-   *
     * Datei ab                                           *
     ******************************************************/
    void PlayWave( Wave *wav )
    {
       unsigned int Page, OffSet;
       unsigned char TimeConstant = (65536 - ( 256000000 / wav->Frequency ) ) >> 8;
       long LinearAdress = FP_SEG( wav->Sample );
       LinearAdress = ( LinearAdress << 4 ) + FP_OFF( wav->Sample );
       Page = LinearAdress >> 16;
       OffSet = LinearAdress & 0xFFFF;
    
       outportb( DSP_READ_DATA, 5 );
       outportb( DSP_BUFFER_STATUS, 0 );
       outportb( 0x0B, 0x49 ); 
       outportb( 0x02, OffSet & 0x100 ); 
       outportb( 0x02, OffSet >> 8 ); 
       outportb( 0x83, Page ); 
       outportb( 0x03, wav->Length & 0x100 );
       outportb( 0x03, wav->Length >> 8 );
       outportb( DSP_READ_DATA, 1 );
       WriteDSP( DSP_START_DAC_DMA );
       WriteDSP( wav->Length & 0xFF );
       WriteDSP( wav->Length >> 8 );
       WriteDSP( DSP_SPEAKER_ON );
    }
    
    int main(void)
    {
       FindBaseport();
    
       Wave testwav;
       //if( LoadWave( "snare.wav", &testwav ) == 0 ) 
       LoadWave( "snare.wav", &testwav );
       PlayWave( &testwav );
    
       getch();
       return 0;
    }
    

    Danke schonmal im vorraus!



  • ...Ohje... Da liegt ja wirklich einiges im Argen.
    Um deinen Code komplett durchzusehen und alle Fehler aufzuzaehlen fehlt mir im Moment der Nerv, daher nur ein paar Ansatzpunkte zur SB-Programmierung vom Drueberlesen:
    Zuerst einmal: Dir ist hoffentlich klar, dass dein Code nur im RealMode funktioniert und ein Sample (bzw. hier ganze Wave-Datei) nicht groesser als 64kByte sein darf (was je nach Qualitaet einen ziemlich kurzen Ton ergibt)?
    Gut.

    outportb( DSP_READ_DATA, 5 );
    outportb( DSP_BUFFER_STATUS, 0 );
    

    Irrefuehrend, da das nichts mit dem DSP zu tun hat. Du programmierst hier den DMAC.
    Im Grunde ist dein Vorgehen so weit OK und sollte funktionieren.
    Da du keinen IRQ installiert hast, kannst du dir je nachdem, in welcher Umgebung du dein Programm ausfuehrst, damit erstmal die Soundausgabe blockieren... Mehr als eine Puffer-Wiedergabe ist so ohne jeweils ein Reset jedenfalls nicht drin.
    Ansonsten kann ich dir nur raten, dir nochmal deine ganzen Bit-Manipulationen am Offset, etc. genau anzuschauen. Da liegen die groebsten Fehler.



  • Cruncheee schrieb:

    Ich schreib mir zurzeit eine kleine Funktionssammlung, die mir das programmieren eines DOS-Games ermöglicht (Grafik, Steuerung..usw)

    vermutlich weißt du das schon, aber mit DOS handelst du dir einen riesigen aufwand für kram ein, den du bei windows geschenkt kriegst. selbst wenn es dir nur um das hintergrundwissen geht, wirst du dir kaum noch relevantes erarbeiten können.

    wenn du es um der sache willen programmieren willst, viel spaß - ansonsten denk lieber noch mal über windows oder vielleicht linux nach.


Anmelden zum Antworten