Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

input_mod.cpp

Go to the documentation of this file.
00001 /*
00002   How It Works
00003 
00004   
00005   MikMod/Integration
00006   --
00007   We actually implement a MikMod output driver to render PCM
00008   data.  When read() needs more PCM data, we ask MikMod to
00009   update until we have enough data.
00010 */
00011 
00012 
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include "input_mod.h"
00016 #include "debug.h"
00017 #include "utility.h"
00018 
00019 
00020 namespace audiere {
00021 
00022   MD_DEVICE MODInputStream::drv_audiere = {
00023     "Audiere Output",
00024     "Internal Audiere Output Driver",
00025     0,
00026     VC_MAXVOICES,
00027 
00028     NULL,
00029     NULL,
00030     NULL,
00031 
00032     // Sample loading
00033     VC_SampleAlloc,
00034     VC_SampleGetPtr,
00035     VC_SampleLoad,
00036     VC_SampleUnload,
00037     VC_SampleSpace,
00038     VC_SampleLength,
00039 
00040     // Detection and initialization
00041     ADR_IsThere,
00042     ADR_Init,
00043     ADR_Exit,
00044     ADR_Update,
00045     VC_Preempt,
00046 
00047     NULL,
00048     ADR_SetSoftVoices,
00049 
00050     ADR_SetMode,
00051     ADR_GetMode,
00052 
00053     VC_SetVolume,
00054     VC_GetVolume,
00055 
00056     // Voice control and voice information
00057     VC_GetActiveVoices,
00058 
00059     VC_VoiceSetVolume,
00060     VC_VoiceGetVolume,
00061     VC_VoiceSetFrequency,
00062     VC_VoiceGetFrequency,
00063     VC_VoiceSetPosition,
00064     VC_VoiceGetPosition,
00065     VC_VoiceSetSurround,
00066     VC_VoiceSetResonance,
00067 
00068     VC_VoicePlay,
00069     VC_VoiceResume,
00070     VC_VoiceStop,
00071     VC_VoiceStopped,
00072     VC_VoiceReleaseSustain,
00073 
00074     VC_VoiceRealVolume
00075   };
00076 
00077 
00078   MODInputStream::MODInputStream() {
00079     m_file = 0;
00080 
00081     m_driver = 0;
00082     m_module = 0;
00083     m_player = 0;
00084 
00085     m_samples_left = 0;
00086     m_next_sample = m_sample_buffer;
00087 
00088     m_at_eof = false;
00089   }
00090 
00091 
00092   MODInputStream::~MODInputStream() {
00093     if (m_player) {
00094       Player_Free(m_player);
00095     }
00096     if (m_module) {
00097       Unimod_Free(m_module);
00098     }
00099     if (m_driver) {
00100       Mikmod_Exit(m_driver);
00101     }
00102   }
00103 
00104 
00105   bool
00106   MODInputStream::initialize(File* file) {
00107     m_file = file;
00108 
00109     // first time we run, initialize MikMod
00110     static bool initialized = false;
00111     if (!initialized) {
00112       ADR_GUARD("Initializing MikMod");
00113 
00114       Mikmod_RegisterLoader(load_it);
00115       Mikmod_RegisterLoader(load_xm);
00116       Mikmod_RegisterLoader(load_s3m);
00117       Mikmod_RegisterLoader(load_mod);
00118       Mikmod_RegisterLoader(load_stm);
00119     
00120       Mikmod_RegisterDriver(drv_audiere);
00121 
00122       initialized = true;
00123     }
00124 
00125     m_stream.fp      = (FILE*)this;
00126     m_stream.dp      = 0;
00127     m_stream.iobase  = 0;
00128     m_stream.seekpos = 0;
00129     m_stream.fread   = MMRead;
00130     m_stream.fwrite  = MMWrite;
00131     m_stream.fgetc   = MMGetC;
00132     m_stream.fputc   = MMPutC;
00133     m_stream.fseek   = MMSeek;
00134     m_stream.ftell   = MMTell;
00135     m_stream.feof    = MMEof;
00136 
00137     m_samples_left = 0;
00138     m_next_sample  = m_next_sample;
00139 
00140     m_at_eof = false;
00141 
00142     // create output device
00143     m_driver = Mikmod_Init(
00144       44100, 2400, this, MD_STEREO, CPU_AUTODETECT,
00145       DMODE_16BITS | DMODE_INTERP | DMODE_NOCLICK | DMODE_RESONANCE);
00146     if (!m_driver) {
00147       m_file = 0;
00148       return false;
00149     }
00150 
00151     ADR_LOG("Mikmod_Init succeeded");
00152 
00153     // load the song
00154     m_module = Unimod_LoadFP(
00155       m_driver,
00156       &m_stream,
00157       &m_stream,
00158       MM_STATIC);
00159     if (!m_module) {
00160       Mikmod_Exit(m_driver);
00161       m_driver = 0;
00162       m_file = 0;
00163       return false;
00164     }
00165 
00166     ADR_LOG("Unimod_LoadFP succeeded");
00167 
00168     // load the samples (???)
00169     if (SL_LoadSamples(m_driver)) {
00170       Unimod_Free(m_module);
00171       m_module = 0;
00172       Mikmod_Exit(m_driver);
00173       m_driver = 0;
00174       m_file = 0;
00175       return false;
00176     }
00177 
00178     ADR_LOG("SL_LoadSamples succeeded");
00179 
00180     // create a player
00181     m_player = Player_InitSong(m_module, NULL, 0, 64);
00182     if (!m_player) {
00183       Unimod_Free(m_module);
00184       m_module = 0;
00185       Mikmod_Exit(m_driver);
00186       m_driver = 0;
00187       m_file = 0;
00188       return false;
00189     }
00190 
00191     ADR_LOG("Player_InitSong succeeded");
00192 
00193     // start playback of the module
00194     // we won't actually get samples until the read call
00195     Player_Start(m_player);
00196 
00197     ADR_LOG("Player_Start succeeded");
00198 
00199     return true;
00200   }
00201 
00202 
00203   void
00204   MODInputStream::getFormat(
00205     int& channel_count,
00206     int& sample_rate,
00207     SampleFormat& sample_format)
00208   {
00209     channel_count = 2;
00210     sample_rate   = 44100;
00211     sample_format = SF_S16;
00212   }
00213 
00214 
00215   int
00216   MODInputStream::read(int frame_count, void* buffer) {
00217     ADR_GUARD("MODInputStream::read");
00218 
00219     u32* out = static_cast<u32*>(buffer);
00220 
00221     int total_written = 0;
00222     while (frame_count > 0) {
00223 
00224       // if there are no frames in the buffer, tell mikmod to give us a few
00225       if (m_samples_left == 0) {
00226 
00227         // if the song isn't playing any more, just stop
00228         if (!Player_Active(m_player)) {
00229           break;
00230         }
00231 
00232         Mikmod_Update(m_driver);
00233       }
00234 
00235       // read data out of the buffer
00236       u32 samples_to_read = std::min<u32>(
00237         frame_count,
00238         m_samples_left);
00239       memcpy(out, m_next_sample, samples_to_read * 4);
00240 
00241       // update pointers and indices and counts, oh my
00242       out            += samples_to_read;    
00243       m_next_sample  += samples_to_read;
00244       m_samples_left -= samples_to_read;
00245       frame_count    -= samples_to_read;
00246       total_written  += samples_to_read;
00247     }
00248 
00249     return total_written;
00250   }
00251 
00252 
00253   void
00254   MODInputStream::reset() {
00255     ADR_GUARD("MOD_Reset");
00256 
00257     m_samples_left = 0;
00258     m_next_sample  = m_sample_buffer;
00259 
00260     Player_Stop(m_player);
00261     Player_Start(m_player);
00262   }
00263 
00264 
00265   BOOL
00266   MODInputStream::ADR_IsThere() {
00267     return 1;
00268   }
00269 
00270 
00271   BOOL
00272   MODInputStream::ADR_Init(MDRIVER* md, uint latency, void* optstr) {
00273     ADR_GUARD("ADR_Init");
00274 
00275     md->device.vc = VC_Init();
00276     if (!md->device.vc) {
00277       return 1;
00278     }
00279 
00280     md->device.local = optstr;
00281     return 0;
00282   }
00283 
00284 
00285   void
00286   MODInputStream::ADR_Exit(MDRIVER* md) {
00287     ADR_GUARD("ADR_Exit");
00288 
00289     VC_Exit(md->device.vc);
00290   }
00291 
00292 
00293   void
00294   MODInputStream::ADR_Update(MDRIVER* md) {
00295     ADR_GUARD("ADR_Update");
00296 
00297     MODInputStream* stream = reinterpret_cast<MODInputStream*>(md->device.local);
00298 
00299     // we should only write into the buffer if it's empty
00300     if (stream->m_samples_left != 0) {
00301       return;
00302     }
00303 
00304     VC_WriteBytes(
00305       md,
00306       (signed char*)stream->m_sample_buffer,
00307       SAMPLE_BUFFER_SIZE * sizeof(u32));
00308     stream->m_samples_left = SAMPLE_BUFFER_SIZE;
00309     stream->m_next_sample = stream->m_sample_buffer;
00310   }
00311 
00312 
00313   BOOL
00314   MODInputStream::ADR_SetSoftVoices(MDRIVER* md, uint voices) {
00315     return VC_SetSoftVoices(md->device.vc, voices);
00316   }
00317 
00318 
00319   BOOL
00320   MODInputStream::ADR_SetMode(
00321     MDRIVER* md, uint mixspeed, uint mode,
00322     uint channels, uint cpumode)
00323   {
00324     return VC_SetMode(md->device.vc, mixspeed, mode, channels, cpumode);
00325   }
00326 
00327 
00328   void
00329   MODInputStream::ADR_GetMode(
00330     MDRIVER* md, uint* mixspeed, uint* mode,
00331     uint* channels, uint* cpumode)
00332   {
00333     VC_GetMode(md->device.vc, mixspeed, mode, channels, cpumode);
00334   }
00335 
00336 
00337   int CRT_CALL
00338   MODInputStream::MMRead(
00339     void* buffer, size_t size, size_t count, FILE* stream)
00340   {
00341     MODInputStream* istream = reinterpret_cast<MODInputStream*>(stream);
00342     int result = istream->m_file->read(buffer, size * count) / size;
00343     if (result == 0) {
00344       istream->m_at_eof = true;
00345     }
00346     return result;
00347   }
00348 
00349 
00350   int CRT_CALL
00351   MODInputStream::MMWrite(
00352     const void* buffer, size_t size, size_t count, FILE* stream)
00353   {
00354     // we can't write
00355     return -1;
00356   }
00357 
00358 
00359   int CRT_CALL
00360   MODInputStream::MMGetC(FILE* stream) {
00361     unsigned char c;
00362     if (MMRead(&c, 1, 1, stream) == 1) {
00363       return c;
00364     } else {
00365      return EOF;
00366     }
00367   }
00368 
00369 
00370   int CRT_CALL
00371   MODInputStream::MMPutC(int c, FILE* stream) {
00372     char ch = (char)c;
00373     return MMWrite(&ch, 1, 1, stream);
00374   }
00375 
00376 
00377   int CRT_CALL
00378   MODInputStream::MMSeek(FILE* stream, long offset, int origin) {
00379     MODInputStream* istream = reinterpret_cast<MODInputStream*>(stream);
00380     File* file = istream->m_file.get();
00381 
00382     File::SeekMode seek_mode;
00383     switch (origin) {
00384       case SEEK_SET: seek_mode = File::BEGIN;   break;
00385       case SEEK_CUR: seek_mode = File::CURRENT; break;
00386       case SEEK_END: seek_mode = File::END;     break;
00387       default: return -1;
00388     }
00389 
00390     return file->seek(offset, seek_mode) ? 0 : -1;
00391   }
00392 
00393 
00394   int CRT_CALL
00395   MODInputStream::MMTell(FILE* stream) {
00396     MODInputStream* istream = reinterpret_cast<MODInputStream*>(stream);
00397     File* file = istream->m_file.get();
00398     return file->tell();
00399   }
00400 
00401 
00402   int CRT_CALL
00403   MODInputStream::MMEof(FILE* stream) {
00404     MODInputStream* istream = reinterpret_cast<MODInputStream*>(stream);
00405     return istream->m_at_eof ? 1 : 0;
00406   }
00407 
00408 }

Generated on Sat Oct 12 01:43:03 2002 for audiere by doxygen1.2.17