music_modplug.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 01 Jun 2013 22:30:04 -0700
changeset 627 438fb12df34f
parent 625 1d489d8ec2e0
child 639 f8901a7ff3f1
permissions -rw-r--r--
Updated iOS project to include OGG support directly
     1 #ifdef MODPLUG_MUSIC
     2 
     3 #include "music_modplug.h"
     4 
     5 static int current_output_channels=0;
     6 static int music_swap8=0;
     7 static int music_swap16=0;
     8 static ModPlug_Settings settings;
     9 
    10 int modplug_init(SDL_AudioSpec *spec)
    11 {
    12     ModPlug_GetSettings(&settings);
    13     settings.mFlags=MODPLUG_ENABLE_OVERSAMPLING;
    14     current_output_channels=spec->channels;
    15     settings.mChannels=spec->channels>1?2:1;
    16     settings.mBits=spec->format&0xFF;
    17 
    18     music_swap8 = 0;
    19     music_swap16 = 0;
    20 
    21     switch(spec->format)
    22     {
    23         case AUDIO_U8:
    24         case AUDIO_S8: {
    25             if ( spec->format == AUDIO_S8 ) {
    26                 music_swap8 = 1;
    27             }
    28             settings.mBits=8;
    29         }
    30         break;
    31 
    32         case AUDIO_S16LSB:
    33         case AUDIO_S16MSB: {
    34             /* See if we need to correct MikMod mixing */
    35 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    36             if ( spec->format == AUDIO_S16MSB ) {
    37 #else
    38             if ( spec->format == AUDIO_S16LSB ) {
    39 #endif
    40                 music_swap16 = 1;
    41             }
    42             settings.mBits=16;
    43         }
    44         break;
    45 
    46         default: {
    47             Mix_SetError("Unknown hardware audio format");
    48             return -1;
    49         }
    50 
    51     }
    52 
    53     settings.mFrequency=spec->freq; /*TODO: limit to 11025, 22050, or 44100 ? */
    54     settings.mResamplingMode=MODPLUG_RESAMPLE_FIR;
    55     settings.mReverbDepth=0;
    56     settings.mReverbDelay=100;
    57     settings.mBassAmount=0;
    58     settings.mBassRange=50;
    59     settings.mSurroundDepth=0;
    60     settings.mSurroundDelay=10;
    61     settings.mLoopCount=0;
    62     ModPlug_SetSettings(&settings);
    63     return 0;
    64 }
    65 
    66 /* Uninitialize the music players */
    67 void modplug_exit()
    68 {
    69 }
    70 
    71 /* Set the volume for a modplug stream */
    72 void modplug_setvolume(modplug_data *music, int volume)
    73 {
    74     ModPlug_SetMasterVolume(music->file, volume*4);
    75 }
    76 
    77 /* Load a modplug stream from an SDL_RWops object */
    78 modplug_data *modplug_new_RW(SDL_RWops *src, int freesrc)
    79 {
    80     modplug_data *music = NULL;
    81     Sint64 offset;
    82     size_t sz;
    83     char *buf;
    84 
    85     offset = SDL_RWtell(src);
    86     SDL_RWseek(src, 0, RW_SEEK_END);
    87     sz = (size_t)(SDL_RWtell(src) - offset);
    88     SDL_RWseek(src, offset, RW_SEEK_SET);
    89     buf = (char*)SDL_malloc(sz);
    90     if (buf) {
    91         if (SDL_RWread(src, buf, sz, 1) == 1) {
    92             music = (modplug_data*)SDL_malloc(sizeof(modplug_data));
    93             if (music) {
    94                 music->playing = 0;
    95                 music->file = ModPlug_Load(buf, sz);
    96                 if (!music->file) {
    97                     SDL_free(music);
    98                     music = NULL;
    99                 }
   100             } else {
   101                 SDL_OutOfMemory();
   102             }
   103         }
   104         SDL_free(buf);
   105     } else {
   106         SDL_OutOfMemory();
   107     }
   108     if (music && freesrc) {
   109         SDL_RWclose(src);
   110     }
   111     return music;
   112 }
   113 
   114 /* Start playback of a given modplug stream */
   115 void modplug_play(modplug_data *music)
   116 {
   117     ModPlug_Seek(music->file,0);
   118     music->playing=1;
   119 }
   120 
   121 /* Return non-zero if a stream is currently playing */
   122 int modplug_playing(modplug_data *music)
   123 {
   124     return music && music->playing;
   125 }
   126 
   127 /* Play some of a stream previously started with modplug_play() */
   128 int modplug_playAudio(modplug_data *music, Uint8 *stream, int len)
   129 {
   130     if (current_output_channels > 2) {
   131         int small_len = 2 * len / current_output_channels;
   132         int i;
   133         Uint8 *src, *dst;
   134 
   135         i=ModPlug_Read(music->file, stream, small_len);
   136         if(i<small_len)
   137         {
   138             SDL_memset(stream+i,0,small_len-i);
   139             music->playing=0;
   140         }
   141         /* and extend to len by copying channels */
   142         src = stream + small_len;
   143         dst = stream + len;
   144 
   145         switch (settings.mBits) {
   146             case 8:
   147                 for ( i=small_len/2; i; --i ) {
   148                     src -= 2;
   149                     dst -= current_output_channels;
   150                     dst[0] = src[0];
   151                     dst[1] = src[1];
   152                     dst[2] = src[0];
   153                     dst[3] = src[1];
   154                     if (current_output_channels == 6) {
   155                         dst[4] = src[0];
   156                         dst[5] = src[1];
   157                     }
   158                 }
   159                 break;
   160             case 16:
   161                 for ( i=small_len/4; i; --i ) {
   162                     src -= 4;
   163                     dst -= 2 * current_output_channels;
   164                     dst[0] = src[0];
   165                     dst[1] = src[1];
   166                     dst[2] = src[2];
   167                     dst[3] = src[3];
   168                     dst[4] = src[0];
   169                     dst[5] = src[1];
   170                     dst[6] = src[2];
   171                     dst[7] = src[3];
   172                     if (current_output_channels == 6) {
   173                         dst[8] = src[0];
   174                         dst[9] = src[1];
   175                         dst[10] = src[2];
   176                         dst[11] = src[3];
   177                     }
   178                 }
   179                 break;
   180         }
   181     } else {
   182         int i=ModPlug_Read(music->file, stream, len);
   183         if(i<len)
   184         {
   185             SDL_memset(stream+i,0,len-i);
   186             music->playing=0;
   187         }
   188     }
   189     if ( music_swap8 ) {
   190         Uint8 *dst;
   191         int i;
   192 
   193         dst = stream;
   194         for ( i=len; i; --i ) {
   195             *dst++ ^= 0x80;
   196         }
   197     } else
   198     if ( music_swap16 ) {
   199         Uint8 *dst, tmp;
   200         int i;
   201 
   202         dst = stream;
   203         for ( i=(len/2); i; --i ) {
   204             tmp = dst[0];
   205             dst[0] = dst[1];
   206             dst[1] = tmp;
   207             dst += 2;
   208         }
   209     }
   210     return 0;
   211 }
   212 
   213 /* Stop playback of a stream previously started with modplug_play() */
   214 void modplug_stop(modplug_data *music)
   215 {
   216     music->playing=0;
   217 }
   218 
   219 /* Close the given modplug stream */
   220 void modplug_delete(modplug_data *music)
   221 {
   222     ModPlug_Unload(music->file);
   223     SDL_free(music);
   224 }
   225 
   226 /* Jump (seek) to a given position (time is in seconds) */
   227 void modplug_jump_to_time(modplug_data *music, double time)
   228 {
   229     ModPlug_Seek(music->file,(int)(time*1000));
   230 }
   231 
   232 #endif