Browse Source

More WIP music streaming.

Mark Sibly 7 years ago
parent
commit
595344932a
2 changed files with 95 additions and 34 deletions
  1. 2 0
      modules/mojo/audio/audio.monkey2
  2. 93 34
      modules/mojo/audio/native/bbmusic.cpp

+ 2 - 0
modules/mojo/audio/audio.monkey2

@@ -50,6 +50,8 @@ Class AudioDevice
 			finished()
 			finished()
 		End,True )
 		End,True )
 		
 		
+		path=filesystem.RealPath( path )
+		
 		If Not playMusic( path,callback,channel._alSource ) 
 		If Not playMusic( path,callback,channel._alSource ) 
 			async.DestroyAsyncCallback( callback )
 			async.DestroyAsyncCallback( callback )
 			channel.Discard()
 			channel.Discard()

+ 93 - 34
modules/mojo/audio/native/bbmusic.cpp

@@ -1,19 +1,68 @@
 
 
 #include "bbmusic.h"
 #include "bbmusic.h"
 
 
-#include "../../../openal/native/bbopenal.h"
-
 #include "../../../std/async/native/async.h"
 #include "../../../std/async/native/async.h"
 #include "../../../std/async/native/async_cb.h"
 #include "../../../std/async/native/async_cb.h"
-
 #include "../../../stb-vorbis/native/stb-vorbis.h"
 #include "../../../stb-vorbis/native/stb-vorbis.h"
+#include "../../../openal/native/bbopenal.h"
+
+#if __ANDROID__
+
+#include "../../../sdl2/SDL/src/core/android/SDL_android.h"
+
+#endif
 
 
 namespace bbMusic{
 namespace bbMusic{
 
 
+#if __ANDROID__
+	
+	int android_read( void *cookie,char *buf,int size ){
+	
+	  return AAsset_read( (AAsset*)cookie,buf,size );
+	}
+	
+	int android_write( void *cookie,const char* buf,int size ){
+	
+	  return EACCES; // can't provide write access to the apk
+	}
+	
+	fpos_t android_seek( void *cookie,fpos_t offset,int whence ){
+	
+	  return AAsset_seek( (AAsset*)cookie,offset,whence );
+	}
+	
+	int android_close(void* cookie) {
+	
+	  AAsset_close( (AAsset*)cookie );
+	  return 0;
+	}
+	
+#endif
+	
+	FILE *fopen( const char *path,const char *mode ){
+	
+#if __ANDROID__
+		if( !strncmp( path,"asset::",7 ) ){
+			
+			AAssetManager *assetManager=Android_JNI_GetAssetManager();
+			if( !assetManager ) return 0;
+			
+	  		AAsset* asset=AAssetManager_open( assetManager,path+7,0 );
+			if( !asset ) return 0;
+	
+	  		return funopen( asset,android_read,android_write,android_seek,android_close );
+		}
+#endif
+		return ::fopen( path,mode );
+	}
+
 	bool playMusic( const char *path,int callback,int alsource ){
 	bool playMusic( const char *path,int callback,int alsource ){
 	
 	
+		FILE *file=fopen( path,"rb" );
+		if( !file ) return false;
+	
 		int error=0;
 		int error=0;
-		stb_vorbis *vorbis=stb_vorbis_open_filename( path,&error,0 );
+		stb_vorbis *vorbis=stb_vorbis_open_file( file,0,&error,0 );
 		if( !vorbis ) return false;
 		if( !vorbis ) return false;
 		
 		
 		std::thread thread( [=](){
 		std::thread thread( [=](){
@@ -21,43 +70,54 @@ namespace bbMusic{
 			ALuint source=alsource;
 			ALuint source=alsource;
 	
 	
 			stb_vorbis_info info=stb_vorbis_get_info( vorbis );
 			stb_vorbis_info info=stb_vorbis_get_info( vorbis );
+//			int length=stb_vorbis_stream_length_in_samples( vorbis );
+//			float duration=stb_vorbis_stream_length_in_seconds( vorbis );
+//			bb_printf( "vorbis length=%i, duration=%f, info.sample_rate=%i, info.channels=%i\n",length,duration,info.sample_rate,info.channels );
 
 
-			int length=stb_vorbis_stream_length_in_samples( vorbis );
-			
-			float duration=stb_vorbis_stream_length_in_seconds( vorbis );
-			
-//			printf( "vorbis length=%i, duration=%f, info.sample_rate=%i, info.channels=%i\n",length,duration,info.sample_rate,info.channels );fflush( stdout );
+			ALenum format=(info.channels==2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16);
 
 
-			const int BUFFER_SIZE=2048;
-			int nsamples=(info.channels==2 ? BUFFER_SIZE/4 : BUFFER_SIZE/2);
-			ALenum format=(info.channels==2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO8);
+//			int buffer_size=8192;
+//			int nsamples=buffer_size / (info.channels==2 ? 4 : 2);
+//			int buffer_ms=nsamples*1000/info.sample_rate;
+			
+			int buffer_ms=50;
+			int nsamples=buffer_ms*info.sample_rate/1000;
+			int buffer_size=nsamples * (info.channels==2 ? 4 : 2);
 			
 			
-			//how long a buffer takes to play?
-			int buffer_ms=nsamples*1000/info.sample_rate;
+//			bb_printf( "buffer_size=%i, buffer_ms=%i\n",buffer_size,buffer_ms );
 			
 			
 			//polling for paused occasionally fails with only 2 buffers
 			//polling for paused occasionally fails with only 2 buffers
 			ALuint buffers[3];
 			ALuint buffers[3];
 			alGenBuffers( 3,buffers );
 			alGenBuffers( 3,buffers );
 			
 			
-			alBufferData( buffers[0],format,0,BUFFER_SIZE,info.sample_rate );
-			alBufferData( buffers[1],format,0,BUFFER_SIZE,info.sample_rate );
-			alBufferData( buffers[2],format,0,BUFFER_SIZE,info.sample_rate );
+			short *vorbis_data=new short[buffer_size/2];
 			
 			
-			alSourceQueueBuffers( source,3,buffers );
+			for( int i=0;i<3;++i ){
+				int n=stb_vorbis_get_samples_short_interleaved( vorbis,info.channels,vorbis_data,buffer_size/2 );
+				alBufferData( buffers[i],format,vorbis_data,buffer_size,info.sample_rate );
+			}
 			
 			
-			short *vorbis_data=new short[BUFFER_SIZE/2];
+			alSourceQueueBuffers( source,3,buffers );
 			
 			
 			alSourcePlay( source );
 			alSourcePlay( source );
 			
 			
-//			printf( "Playing music...\n" );fflush( stdout );
+//			bb_printf( "Playing music...\n" );
 			
 			
 			for(;;){
 			for(;;){
 
 
-				int n=stb_vorbis_get_samples_short_interleaved( vorbis,info.channels,vorbis_data,BUFFER_SIZE/2 );
-				if( !n ) break;
-				
 				ALenum state;
 				ALenum state;
 				
 				
+				int n=stb_vorbis_get_samples_short_interleaved( vorbis,info.channels,vorbis_data,buffer_size/2 );
+				if( !n ){
+					//no more data, wait for audio to stop...
+					for(;;){
+						alGetSourcei( source,AL_SOURCE_STATE,&state );
+						if( state==AL_STOPPED ) break;
+						std::this_thread::sleep_for( std::chrono::milliseconds( buffer_ms ) );
+					}
+					break;
+				}
+				
 				for(;;){
 				for(;;){
 					alGetSourcei( source,AL_SOURCE_STATE,&state );
 					alGetSourcei( source,AL_SOURCE_STATE,&state );
 					if( state==AL_STOPPED ) break;
 					if( state==AL_STOPPED ) break;
@@ -65,36 +125,35 @@ namespace bbMusic{
 					ALint processed;
 					ALint processed;
 					alGetSourcei( source,AL_BUFFERS_PROCESSED,&processed );
 					alGetSourcei( source,AL_BUFFERS_PROCESSED,&processed );
 					
 					
-//					if( state!=AL_PLAYING ){
-//						printf( "state=%i\n",state );fflush( stdout );
-//					}
-					
 					if( state==AL_PLAYING && processed ) break;
 					if( state==AL_PLAYING && processed ) break;
-				        
+						
 					std::this_thread::sleep_for( std::chrono::milliseconds( buffer_ms ) );
 					std::this_thread::sleep_for( std::chrono::milliseconds( buffer_ms ) );
 				}
 				}
-				if( state==AL_STOPPED ) break;
+				if( state==AL_STOPPED ){
+//					bb_printf( "AL_STOPPED\n" );
+					break;
+				}
 				
 				
 				ALuint buffer;
 				ALuint buffer;
 				alSourceUnqueueBuffers( source,1,&buffer );
 				alSourceUnqueueBuffers( source,1,&buffer );
 					
 					
-				alBufferData( buffer,format,vorbis_data,BUFFER_SIZE,info.sample_rate );
+				alBufferData( buffer,format,vorbis_data,buffer_size,info.sample_rate );
 				
 				
 				alSourceQueueBuffers( source,1,&buffer );
 				alSourceQueueBuffers( source,1,&buffer );
 			}
 			}
 
 
-//			printf( "Music done.\n" );fflush( stdout );
+//			bb_printf( "Music done.\n" );
 			
 			
 			alSourceStop( source );
 			alSourceStop( source );
 			
 			
-			delete[] vorbis_data;
-			
 			alDeleteBuffers( 2,buffers );
 			alDeleteBuffers( 2,buffers );
 			
 			
-//			alDeleteSources( 1,&source );
+			delete[] vorbis_data;
 			
 			
 			stb_vorbis_close( vorbis );
 			stb_vorbis_close( vorbis );
 			
 			
+			fclose( file );
+			
 			bbAsync::invokeAsyncCallback( callback );
 			bbAsync::invokeAsyncCallback( callback );
 		} );
 		} );