SDL  2.0
SDL_androidaudio.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_AUDIO_DRIVER_ANDROID
24 
25 /* Output audio to Android */
26 
27 #include "SDL_assert.h"
28 #include "SDL_audio.h"
29 #include "../SDL_audio_c.h"
30 #include "SDL_androidaudio.h"
31 
32 #include "../../core/android/SDL_android.h"
33 
34 #include <android/log.h>
35 
36 static SDL_AudioDevice* audioDevice = NULL;
37 static SDL_AudioDevice* captureDevice = NULL;
38 
39 static int
40 ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
41 {
42  SDL_AudioFormat test_format;
43 
44  SDL_assert((captureDevice == NULL) || !iscapture);
45  SDL_assert((audioDevice == NULL) || iscapture);
46 
47  if (iscapture) {
48  captureDevice = this;
49  } else {
50  audioDevice = this;
51  }
52 
53  this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
54  if (this->hidden == NULL) {
55  return SDL_OutOfMemory();
56  }
57 
58  test_format = SDL_FirstAudioFormat(this->spec.format);
59  while (test_format != 0) { /* no "UNKNOWN" constant */
60  if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
61  this->spec.format = test_format;
62  break;
63  }
64  test_format = SDL_NextAudioFormat();
65  }
66 
67  if (test_format == 0) {
68  /* Didn't find a compatible format :( */
69  return SDL_SetError("No compatible audio format!");
70  }
71 
72  if (this->spec.channels > 1) {
73  this->spec.channels = 2;
74  } else {
75  this->spec.channels = 1;
76  }
77 
78  if (this->spec.freq < 8000) {
79  this->spec.freq = 8000;
80  }
81  if (this->spec.freq > 48000) {
82  this->spec.freq = 48000;
83  }
84 
85  /* TODO: pass in/return a (Java) device ID */
86  this->spec.samples = Android_JNI_OpenAudioDevice(iscapture, this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
87 
88  if (this->spec.samples == 0) {
89  /* Init failed? */
90  return SDL_SetError("Java-side initialization failed!");
91  }
92 
94 
95  return 0;
96 }
97 
98 static void
99 ANDROIDAUDIO_PlayDevice(_THIS)
100 {
102 }
103 
104 static Uint8 *
105 ANDROIDAUDIO_GetDeviceBuf(_THIS)
106 {
108 }
109 
110 static int
111 ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
112 {
113  return Android_JNI_CaptureAudioBuffer(buffer, buflen);
114 }
115 
116 static void
117 ANDROIDAUDIO_FlushCapture(_THIS)
118 {
120 }
121 
122 static void
123 ANDROIDAUDIO_CloseDevice(_THIS)
124 {
125  /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
126  so it's safe to terminate the Java side buffer and AudioTrack
127  */
128  Android_JNI_CloseAudioDevice(this->iscapture);
129  if (this->iscapture) {
130  SDL_assert(captureDevice == this);
131  captureDevice = NULL;
132  } else {
133  SDL_assert(audioDevice == this);
134  audioDevice = NULL;
135  }
136  SDL_free(this->hidden);
137 }
138 
139 static int
140 ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
141 {
142  /* Set the function pointers */
143  impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
144  impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
145  impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
146  impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
147  impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice;
148  impl->FlushCapture = ANDROIDAUDIO_FlushCapture;
149 
150  /* and the capabilities */
151  impl->HasCaptureSupport = SDL_TRUE;
152  impl->OnlyHasDefaultOutputDevice = 1;
153  impl->OnlyHasDefaultCaptureDevice = 1;
154 
155  return 1; /* this audio target is available. */
156 }
157 
159  "android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
160 };
161 
162 /* Pause (block) all non already paused audio devices by taking their mixer lock */
163 void ANDROIDAUDIO_PauseDevices(void)
164 {
165  /* TODO: Handle multiple devices? */
166  struct SDL_PrivateAudioData *private;
167  if(audioDevice != NULL && audioDevice->hidden != NULL) {
168  private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
169  if (SDL_AtomicGet(&audioDevice->paused)) {
170  /* The device is already paused, leave it alone */
171  private->resume = SDL_FALSE;
172  }
173  else {
174  SDL_LockMutex(audioDevice->mixer_lock);
175  SDL_AtomicSet(&audioDevice->paused, 1);
176  private->resume = SDL_TRUE;
177  }
178  }
179 
180  if(captureDevice != NULL && captureDevice->hidden != NULL) {
181  private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
182  if (SDL_AtomicGet(&captureDevice->paused)) {
183  /* The device is already paused, leave it alone */
184  private->resume = SDL_FALSE;
185  }
186  else {
187  SDL_LockMutex(captureDevice->mixer_lock);
188  SDL_AtomicSet(&captureDevice->paused, 1);
189  private->resume = SDL_TRUE;
190  }
191  }
192 }
193 
194 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
195 void ANDROIDAUDIO_ResumeDevices(void)
196 {
197  /* TODO: Handle multiple devices? */
198  struct SDL_PrivateAudioData *private;
199  if(audioDevice != NULL && audioDevice->hidden != NULL) {
200  private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
201  if (private->resume) {
202  SDL_AtomicSet(&audioDevice->paused, 0);
203  private->resume = SDL_FALSE;
204  SDL_UnlockMutex(audioDevice->mixer_lock);
205  }
206  }
207 
208  if(captureDevice != NULL && captureDevice->hidden != NULL) {
209  private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
210  if (private->resume) {
211  SDL_AtomicSet(&captureDevice->paused, 0);
212  private->resume = SDL_FALSE;
213  SDL_UnlockMutex(captureDevice->mixer_lock);
214  }
215  }
216 }
217 
218 
219 #endif /* SDL_AUDIO_DRIVER_ANDROID */
220 
221 /* vi: set ts=4 sw=4 expandtab: */
222 
int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
struct SDL_PrivateAudioData * hidden
Definition: SDL_sysaudio.h:189
#define SDL_LockMutex
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:175
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1611
void Android_JNI_WriteAudioBuffer(void)
SDL_atomic_t paused
Definition: SDL_sysaudio.h:168
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:79
Uint16 samples
Definition: SDL_audio.h:174
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define private
Definition: SDL_naclaudio.h:34
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1623
int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
SDL_AudioSpec spec
Definition: loopwave.c:35
AudioBootStrap ANDROIDAUDIO_bootstrap
#define AUDIO_U8
Definition: SDL_audio.h:89
void Android_JNI_FlushCapturedAudio(void)
void * SDL_calloc(size_t nmemb, size_t size)
Uint8 channels
Definition: SDL_audio.h:172
#define _THIS
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
void Android_JNI_CloseAudioDevice(const int iscapture)
void SDL_free(void *mem)
void * Android_JNI_GetAudioBuffer(void)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1632
#define SDL_assert(condition)
Definition: SDL_assert.h:167
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:76
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:82
#define SDL_SetError
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:85
SDL_AudioFormat format
Definition: SDL_audio.h:171
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:83
GLuint buffer
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:81
#define SDL_AtomicSet
#define SDL_AtomicGet
#define SDL_UnlockMutex