Mercurial > sdl-ios-xcode
comparison src/audio/android/SDL_androidaudio.c @ 4995:9f9bea41e88f
Working audio implementation contributed by Joseph Lunderville
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 13 Jan 2011 11:14:20 -0800 |
parents | 58b6bb4a45e9 |
children | 8d7315668e35 |
comparison
equal
deleted
inserted
replaced
4994:e4ed74189d63 | 4995:9f9bea41e88f |
---|---|
16 License along with this library; if not, write to the Free Software | 16 License along with this library; if not, write to the Free Software |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | 18 |
19 Sam Lantinga | 19 Sam Lantinga |
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 | |
22 This file written by Ryan C. Gordon (icculus@icculus.org) | |
23 */ | 21 */ |
24 #include "SDL_config.h" | 22 #include "SDL_config.h" |
25 | 23 |
26 /* Output audio to Android */ | 24 /* Output audio to Android */ |
27 | 25 |
28 #include "SDL_audio.h" | 26 #include "SDL_audio.h" |
29 #include "../SDL_audio_c.h" | 27 #include "../SDL_audio_c.h" |
30 #include "SDL_androidaudio.h" | 28 #include "SDL_androidaudio.h" |
29 | |
31 #include "../../SDL_android.h" | 30 #include "../../SDL_android.h" |
32 | 31 |
33 #include <android/log.h> | 32 #include <android/log.h> |
34 | 33 |
34 static void * audioDevice; | |
35 | |
35 static int | 36 static int |
36 AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) | 37 AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) |
37 { | 38 { |
38 SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); | 39 SDL_AudioFormat test_format; |
39 int valid_datatype = 0; | 40 int valid_datatype = 0; |
40 | 41 |
41 //TODO: Sample rates etc | 42 if (iscapture) { |
42 __android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Open\n"); | 43 //TODO: implement capture |
44 SDL_SetError("Capture not supported on Android"); | |
45 return 0; | |
46 } | |
47 | |
48 if (audioDevice != NULL) { | |
49 SDL_SetError("Only one audio device at a time please!"); | |
50 return 0; | |
51 } | |
52 | |
53 audioDevice = this; | |
43 | 54 |
44 this->hidden = SDL_malloc(sizeof(*(this->hidden))); | 55 this->hidden = SDL_malloc(sizeof(*(this->hidden))); |
45 if (!this->hidden) { | 56 if (!this->hidden) { |
46 SDL_OutOfMemory(); | 57 SDL_OutOfMemory(); |
47 return 0; | 58 return 0; |
48 } | 59 } |
49 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 60 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
50 | 61 |
51 while ((!valid_datatype) && (test_format)) { | 62 test_format = SDL_FirstAudioFormat(this->spec.format); |
52 this->spec.format = test_format; | 63 while (test_format != 0) { // no "UNKNOWN" constant |
53 switch (test_format) { | 64 if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) { |
54 case AUDIO_S8: | 65 this->spec.format = test_format; |
55 /*case AUDIO_S16LSB: */ | |
56 valid_datatype = 1; | |
57 break; | |
58 default: | |
59 test_format = SDL_NextAudioFormat(); | |
60 break; | 66 break; |
61 } | 67 } |
68 test_format = SDL_NextAudioFormat(); | |
62 } | 69 } |
63 | 70 |
71 if (test_format == 0) { | |
72 // Didn't find a compatible format :( | |
73 SDL_SetError("No compatible audio format!"); | |
74 return 0; | |
75 } | |
76 | |
77 if (this->spec.channels > 1) { | |
78 this->spec.channels = 2; | |
79 } else { | |
80 this->spec.channels = 1; | |
81 } | |
82 | |
83 if (this->spec.freq < 8000) { | |
84 this->spec.freq = 8000; | |
85 } | |
86 if (this->spec.freq > 48000) { | |
87 this->spec.freq = 48000; | |
88 } | |
89 | |
90 // TODO: pass in/return a (Java) device ID, also whether we're opening for input or output | |
91 this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples); | |
92 SDL_CalculateAudioSpec(&this->spec); | |
93 | |
94 if (this->spec.samples == 0) { | |
95 // Init failed? | |
96 SDL_SetError("Java-side initialization failed!"); | |
97 return 0; | |
98 } | |
99 | |
64 return 1; | 100 return 1; |
65 } | 101 } |
66 | 102 |
67 static void | 103 static void |
68 AndroidAUD_PlayDevice(_THIS) | 104 AndroidAUD_PlayDevice(_THIS) |
69 { | 105 { |
70 __android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Play\n"); | 106 Android_JNI_WriteAudioBufferAndUnpin(); |
71 | 107 this->hidden->mixbuf = NULL; |
72 | |
73 //playGenericSound(this->hidden->mixbuf, this->hidden->mixlen); | |
74 | |
75 #if 0 | |
76 | |
77 // sound->rate = 22050; /* sample rate = 22050Hz */ | |
78 // sound->vol = 127; /* volume [0..127] for [min..max] */ | |
79 // sound->pan = 64; /* balance [0..127] for [left..right] */ | |
80 // sound->format = 0; /* 0 for 16-bit, 1 for 8-bit */ | |
81 // playSound(sound); | |
82 #endif | |
83 } | 108 } |
84 | |
85 | 109 |
86 static Uint8 * | 110 static Uint8 * |
87 AndroidAUD_GetDeviceBuf(_THIS) | 111 AndroidAUD_GetDeviceBuf(_THIS) |
88 { | 112 { |
89 //__android_log_print(ANDROID_LOG_INFO, "SDL", "****** get device buf\n"); | 113 if (this->hidden->mixbuf == NULL) { |
90 | 114 this->hidden->mixbuf = Android_JNI_PinAudioBuffer(); |
91 | 115 } |
92 // sound->data = this->hidden->mixbuf;/* pointer to raw audio data */ | 116 return this->hidden->mixbuf; |
93 // sound->len = this->hidden->mixlen; /* size of raw data pointed to above */ | |
94 | |
95 | |
96 Android_JNI_UpdateAudioBuffer(this->hidden->mixbuf, this->hidden->mixlen); | |
97 | |
98 return this->hidden->mixbuf; /* is this right? */ | |
99 } | |
100 | |
101 static void | |
102 AndroidAUD_WaitDevice(_THIS) | |
103 { | |
104 /* stub */ | |
105 __android_log_print(ANDROID_LOG_INFO, "SDL", "****** wait device buf\n"); | |
106 } | 117 } |
107 | 118 |
108 static void | 119 static void |
109 AndroidAUD_CloseDevice(_THIS) | 120 AndroidAUD_CloseDevice(_THIS) |
110 { | 121 { |
111 /* stub */ | 122 if (this->hidden != NULL) { |
112 __android_log_print(ANDROID_LOG_INFO, "SDL", "****** close device buf\n"); | 123 if (this->hidden->mixbuf != NULL) { |
124 Android_JNI_WriteAudioBufferAndUnpin(); | |
125 } | |
126 SDL_free(this->hidden); | |
127 this->hidden = NULL; | |
128 } | |
129 Android_JNI_CloseAudioDevice(); | |
130 | |
131 if (audioDevice == this) { | |
132 audioDevice = NULL; | |
133 } | |
113 } | 134 } |
114 | 135 |
115 static int | 136 static int |
116 AndroidAUD_Init(SDL_AudioDriverImpl * impl) | 137 AndroidAUD_Init(SDL_AudioDriverImpl * impl) |
117 { | 138 { |
118 /* Set the function pointers */ | 139 /* Set the function pointers */ |
119 impl->OpenDevice = AndroidAUD_OpenDevice; | 140 impl->OpenDevice = AndroidAUD_OpenDevice; |
120 impl->PlayDevice = AndroidAUD_PlayDevice; | 141 impl->PlayDevice = AndroidAUD_PlayDevice; |
121 impl->WaitDevice = AndroidAUD_WaitDevice; | |
122 impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf; | 142 impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf; |
123 impl->CloseDevice = AndroidAUD_CloseDevice; | 143 impl->CloseDevice = AndroidAUD_CloseDevice; |
124 | 144 |
125 /* and the capabilities */ | 145 /* and the capabilities */ |
146 impl->ProvidesOwnCallbackThread = 1; | |
126 impl->HasCaptureSupport = 0; //TODO | 147 impl->HasCaptureSupport = 0; //TODO |
127 impl->OnlyHasDefaultOutputDevice = 1; | 148 impl->OnlyHasDefaultOutputDevice = 1; |
128 impl->OnlyHasDefaultInputDevice = 1; | 149 impl->OnlyHasDefaultInputDevice = 1; |
129 | |
130 __android_log_print(ANDROID_LOG_INFO, "SDL","Audio init\n"); | |
131 | 150 |
132 return 1; /* this audio target is available. */ | 151 return 1; /* this audio target is available. */ |
133 } | 152 } |
134 | 153 |
135 AudioBootStrap ANDROIDAUD_bootstrap = { | 154 AudioBootStrap ANDROIDAUD_bootstrap = { |
136 "android", "SDL Android audio driver", AndroidAUD_Init, 0 /*1? */ | 155 "android", "SDL Android audio driver", AndroidAUD_Init, 0 /*1? */ |
137 }; | 156 }; |
138 | 157 |
158 /* Called by the Java code to start the audio processing on a thread */ | |
159 void | |
160 Android_RunAudioThread() | |
161 { | |
162 SDL_RunAudio(audioDevice); | |
163 } | |
164 | |
139 /* vi: set ts=4 sw=4 expandtab: */ | 165 /* vi: set ts=4 sw=4 expandtab: */ |