2
0
Эх сурвалжийг харах

Review audio module and examples

raysan5 9 жил өмнө
parent
commit
58d2f70b7e

+ 0 - 1
examples/audio_music_stream.c

@@ -54,7 +54,6 @@ int main()
             {
                 volume = 1.0;
                 framesCounter = 0;
-                PlayMusicStream(1, "resources/audio/another_file.ogg");
             }
 
             SetMusicVolume(volume);

+ 7 - 4
examples/audio_standalone.c

@@ -39,7 +39,8 @@ int main()
     Sound fxWav = LoadSound("resources/audio/weird.wav");         // Load WAV audio file
     Sound fxOgg = LoadSound("resources/audio/tanatana.ogg");      // Load OGG audio file
     
-    PlayMusicStream(0, "resources/audio/guitar_noodling.ogg");
+    Music music = LoadMusicStream("resources/audio/guitar_noodling.ogg");
+    PlayMusicStream(music);
 
     printf("\nPress s or d to play sounds...\n");
     
@@ -59,11 +60,13 @@ int main()
             key = 0;
         }
         
-        UpdateMusicStream(0);
+        UpdateMusicStream(music);
     }
     
-    UnloadSound(fxWav);     // Unload sound data
-    UnloadSound(fxOgg);     // Unload sound data
+    UnloadSound(fxWav);         // Unload sound data
+    UnloadSound(fxOgg);         // Unload sound data
+    
+    UnloadMusicStream(music);   // Unload music stream data
     
     CloseAudioDevice();
     

+ 63 - 116
src/audio.c

@@ -86,13 +86,13 @@
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
-#define MAX_STREAM_BUFFERS          2             // Number of buffers for each audio stream
+#define MAX_STREAM_BUFFERS          2    // Number of buffers for each audio stream
 
 // NOTE: Music buffer size is defined by number of samples, independent of sample size
 // After some math, considering a sampleRate of 48000, a buffer refill rate of 1/60 seconds
 // and double-buffering system, I concluded that a 4096 samples buffer should be enough
-// In case of music-stalls, just inclease this number
-#define AUDIO_BUFFER_SIZE        4096             // PCM data samples (i.e. short: 32Kb)
+// In case of music-stalls, just increase this number
+#define AUDIO_BUFFER_SIZE        4096    // PCM data samples (i.e. short: 32Kb)
 
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
@@ -141,12 +141,12 @@ static Wave LoadWAV(const char *fileName);         // Load WAV file
 static Wave LoadOGG(char *fileName);               // Load OGG file
 static void UnloadWave(Wave wave);                 // Unload wave data
 
-static AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels);
-static void CloseAudioStream(AudioStream stream); // Frees mix channel
-static int BufferAudioStream(AudioStream stream, void *data, int numberElements); // Pushes more audio data into mix channel
-
 static bool BufferMusicStream(Music music, int numBuffersToProcess);  // Fill music buffers with data
 
+static AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels);
+static void BufferAudioStream(AudioStream stream, void *data, int numSamples);
+static void CloseAudioStream(AudioStream stream);
+
 #if defined(AUDIO_STANDALONE)
 const char *GetExtension(const char *fileName);     // Get the extension for a filename
 void TraceLog(int msgType, const char *text, ...);  // Outputs a trace log message (INFO, ERROR, WARNING)
@@ -492,27 +492,23 @@ Music LoadMusicStream(char *fileName)
         // Open ogg audio stream
         music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
 
-        if (music->ctxOgg == NULL)
-        {
-            TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
-        }
+        if (music->ctxOgg == NULL)  TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
         else
         {
             stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg);  // Get Ogg file info
-
-            TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
-            TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels);
-            TraceLog(DEBUG, "[%s] Temp memory required: %i", fileName, info.temp_memory_required);
+            //float totalLengthSeconds = stb_vorbis_stream_length_in_seconds(music->ctxOgg);
 
             // TODO: Support 32-bit sampleSize OGGs
             music->stream = InitAudioStream(info.sample_rate, 16, info.channels);
-            
             music->totalSamples = (unsigned int)stb_vorbis_stream_length_in_samples(music->ctxOgg)*info.channels;
             music->samplesLeft = music->totalSamples;
-            //float totalLengthSeconds = stb_vorbis_stream_length_in_seconds(music->ctxOgg);
-
             music->ctxType = MUSIC_AUDIO_OGG;
             music->loop = true;                  // We loop by default
+
+            TraceLog(DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate);
+            TraceLog(DEBUG, "[%s] OGG channels: %i", fileName, info.channels);
+            TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required);
+            
         }
     }
     else if (strcmp(GetExtension(fileName), "xm") == 0)
@@ -523,17 +519,15 @@ Music LoadMusicStream(char *fileName)
         {
             jar_xm_set_max_loop_count(music->ctxXm, 0);     // Set infinite number of loops
 
-            music->totalSamples = (unsigned int)jar_xm_get_remaining_samples(music->ctxXm);
-            music->samplesLeft = music->totalSamples;
-
-            TraceLog(INFO, "[%s] XM number of samples: %i", fileName, music->totalSamples);
-            TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
-            
             // NOTE: Only stereo is supported for XM
             music->stream = InitAudioStream(48000, 32, 2);
-            
+            music->totalSamples = (unsigned int)jar_xm_get_remaining_samples(music->ctxXm);
+            music->samplesLeft = music->totalSamples;
             music->ctxType = MUSIC_MODULE_XM;
             music->loop = true;
+            
+            TraceLog(DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples);
+            TraceLog(DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
         }
         else TraceLog(WARNING, "[%s] XM file could not be opened", fileName);
     }
@@ -543,16 +537,14 @@ Music LoadMusicStream(char *fileName)
 
         if (jar_mod_load_file(&music->ctxMod, fileName))
         {
+            music->stream = InitAudioStream(48000, 16, 2);
             music->totalSamples = (unsigned int)jar_mod_max_samples(&music->ctxMod);
             music->samplesLeft = music->totalSamples;
+            music->ctxType = MUSIC_MODULE_MOD;
+            music->loop = true;
 
             TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, music->samplesLeft);
             TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
-
-            music->stream = InitAudioStream(48000, 16, 2);
-
-            music->ctxType = MUSIC_MODULE_MOD;
-            music->loop = true;
         }
         else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName);
     }
@@ -799,42 +791,18 @@ static void CloseAudioStream(AudioStream stream)
 }
 
 // Push more audio data into audio stream, only one buffer per call
-// NOTE: Returns number of samples that were processed
-static int BufferAudioStream(AudioStream stream, void *data, int numberElements)
-{
-    if (!data || !numberElements)   
-    { 
-        // Pauses audio until data is given
-        alSourcePause(stream.source);
-        return 0;
-    }
-    
+static void BufferAudioStream(AudioStream stream, void *data, int numSamples)
+{   
     ALuint buffer = 0;
     alSourceUnqueueBuffers(stream.source, 1, &buffer);
     
-    if (!buffer) return 0;
-    
-    // Reference
-    //void alBufferData(ALuint bufferName, ALenum format, const ALvoid *data, ALsizei size, ALsizei frequency);
-    
-    // ALuint bufferName: buffer id
-    // ALenum format: Valid formats are 
-    //      AL_FORMAT_MONO8,        // unsigned char
-    //      AL_FORMAT_MONO16,       // short
-    //      AL_FORMAT_STEREO8,
-    //      AL_FORMAT_STEREO16      // stereo data is interleaved: left+right channels sample
-    //      AL_FORMAT_MONO_FLOAT32 (extension)
-    //      AL_FORMAT_STEREO_FLOAT32 (extension)
-    // ALsizei size: Number of bytes, must be coherent with format
-    // ALsizei frequency: sample rate
-    
-    if (stream.sampleSize == 8) alBufferData(buffer, stream.format, (unsigned char *)data, numberElements*sizeof(unsigned char), stream.sampleRate);
-    else if (stream.sampleSize == 16) alBufferData(buffer, stream.format, (short *)data, numberElements*sizeof(short), stream.sampleRate);
-    else if (stream.sampleSize == 32) alBufferData(buffer, stream.format, (float *)data, numberElements*sizeof(float), stream.sampleRate);
+    //TraceLog(DEBUG, "Buffer to refill: %i", buffer);
 
-    alSourceQueueBuffers(stream.source, 1, &buffer);
+    if (stream.sampleSize == 8) alBufferData(buffer, stream.format, (unsigned char *)data, numSamples*sizeof(unsigned char), stream.sampleRate);
+    else if (stream.sampleSize == 16) alBufferData(buffer, stream.format, (short *)data, numSamples*sizeof(short), stream.sampleRate);
+    else if (stream.sampleSize == 32) alBufferData(buffer, stream.format, (float *)data, numSamples*sizeof(float), stream.sampleRate);
 
-    return numberElements;
+    alSourceQueueBuffers(stream.source, 1, &buffer);
 }
 
 // Fill music buffers with new data from music stream
@@ -845,70 +813,49 @@ static bool BufferMusicStream(Music music, int numBuffersToProcess)
 
     int size = 0;              // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts
     bool active = true;        // We can get more data from stream (not finished)
-
-    if (music->ctxType == MUSIC_MODULE_XM) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes.
+    
+    for (int i = 0; i < numBuffersToProcess; i++)
     {
-        for (int i = 0; i < numBuffersToProcess; i++)
-        {
-            if (music->samplesLeft >= AUDIO_BUFFER_SIZE) size = AUDIO_BUFFER_SIZE/2;
-            else size = music->samplesLeft/2;
-
-            // Read 2*shorts and moves them to buffer+size memory location
-            jar_xm_generate_samples(music->ctxXm, pcmf, size); 
-            
-            BufferAudioStream(music->stream, pcmf, size*2);
-
-            music->samplesLeft -= size;
+        if (music->samplesLeft >= AUDIO_BUFFER_SIZE) size = AUDIO_BUFFER_SIZE;
+        else size = music->samplesLeft;
 
-            if (music->samplesLeft <= 0)
-            {
-                active = false;
-                break;
-            }
-        }
-    }
-    else if (music->ctxType == MUSIC_MODULE_MOD)
-    {
-        for (int i = 0; i < numBuffersToProcess; i++)
+        switch (music->ctxType)
         {
-            if (music->samplesLeft >= AUDIO_BUFFER_SIZE) size = AUDIO_BUFFER_SIZE/2;
-            else size = music->samplesLeft/2;
-
-            jar_mod_fillbuffer(&music->ctxMod, pcm, size, 0);
-            
-            BufferAudioStream(music->stream, pcm, size*2);
-
-            music->samplesLeft -= size;
-
-            if (music->samplesLeft <= 0)
+            case MUSIC_AUDIO_OGG: 
             {
-                active = false;
-                break;
-            }
+                // NOTE: Returns the number of samples to process (should be the same as size)
+                int numSamples = stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, pcm, size);
+
+                BufferAudioStream(music->stream, pcm, numSamples*music->stream.channels);
+                music->samplesLeft -= (numSamples*music->stream.channels);
+                
+            } break;
+            case MUSIC_MODULE_XM: 
+            {
+                // NOTE: Output buffer is 2*numsamples elements (left and right value for each sample)
+                jar_xm_generate_samples(music->ctxXm, pcmf, size/2);
+                BufferAudioStream(music->stream, pcmf, size);           // Using 32bit PCM data
+                music->samplesLeft -= (size/2);
+                
+            } break;
+            case MUSIC_MODULE_MOD: 
+            {
+                // NOTE: Output buffer size is nbsample*channels (default: 48000Hz, 16bit, Stereo)
+                jar_mod_fillbuffer(&music->ctxMod, pcm, size/2, 0); 
+                BufferAudioStream(music->stream, pcm, size);
+                music->samplesLeft -= (size/2);
+                
+            } break;
+            default: break;
         }
-    }
-    else if (music->ctxType == MUSIC_AUDIO_OGG)
-    {
-        if (music->samplesLeft >= AUDIO_BUFFER_SIZE) size = AUDIO_BUFFER_SIZE;
-        else size = music->samplesLeft;
 
-        for (int i = 0; i < numBuffersToProcess; i++)
+        if (music->samplesLeft <= 0)
         {
-            // NOTE: Returns the number of samples stored per channel
-            int numSamples = stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, pcm, size);
-            
-            BufferAudioStream(music->stream, pcm, numSamples*music->stream.channels);
-            
-            music->samplesLeft -= (numSamples*music->stream.channels);
-
-            if (music->samplesLeft <= 0)
-            {
-                active = false;
-                break;
-            }
+            active = false;
+            break;
         }
     }
-
+    
     return active;
 }
 

+ 5 - 3
templates/android_project/jni/basic_game.c

@@ -43,7 +43,8 @@ void android_main(struct android_app *app)
 
     int framesCounter = 0;          // Used to count frames
     
-    PlayMusicStream(0, "ambient.ogg");
+    Music ambient = LoadMusicStream("ambient.ogg");
+    PlayMusicStream(ambient);
     
     SetTargetFPS(60);               // Not required on Android, already locked to 60 fps
     //--------------------------------------------------------------------------------------
@@ -53,7 +54,7 @@ void android_main(struct android_app *app)
     {
         // Update
         //----------------------------------------------------------------------------------
-        UpdateMusicStream(0);
+        UpdateMusicStream(ambient);
         
         switch(currentScreen) 
         {
@@ -158,7 +159,8 @@ void android_main(struct android_app *app)
     
     // TODO: Unload all loaded data (textures, fonts, audio) here!
 
-    UnloadSound(fx);        // Unload sound data
+    UnloadSound(fx);            // Unload sound data
+    UnloadMusicStream(ambient); // Unload music stream data
     
     CloseAudioDevice();     // Close audio device (music streaming is automatically stopped)