Subversion Repositories Kolibri OS

Rev

Rev 9288 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "SDL_audio.h"
  2. #include <stdint.h>
  3. #include <sys/ksys.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sound.h>
  7. #include <stdio.h>
  8.  
  9. extern void SDL_printf(const char * fmt,...);
  10.  
  11. #define AUDIO_THREAD_STACK_SIZE 40960
  12.  
  13. static ksys_thread_t thread_info;
  14. static int bInitialized = 0;
  15. static SNDBUF hBuff = 0;
  16. static uint8_t* data = NULL;
  17. static int audio_tid = 0;
  18. static int main_slot;
  19. static uint32_t main_tid;
  20. static char audio_thread_stack[AUDIO_THREAD_STACK_SIZE];
  21. static uint32_t used_format = 0;
  22. static int mix_size = 0;
  23.  
  24. static void (*callback)(void* userdata, Uint8* stream, int len);
  25. static void* userdata;
  26.  
  27. int SDL_AudioInit(const char* driver_name)
  28. {
  29.     if (bInitialized) {
  30.         SDL_SetError("Audio already initialized");
  31.         return -1;
  32.     }
  33.     int ver;
  34.     if (InitSound(&ver)) {
  35.         SDL_printf("Warning: cannot load drivers, sound output will be disabled\n");
  36.         return 0;
  37.     }
  38.     bInitialized = 1;
  39.     return 0;
  40. }
  41.  
  42. void SDL_AudioQuit(void) {/*STUB*/}
  43.  
  44. char* SDL_AudioDriverName(char* namebuf, int maxlen)
  45. {
  46.     if (!bInitialized)
  47.             return NULL;
  48.     strncpy(namebuf,"KolibriAudio",maxlen);
  49.     return namebuf;
  50. }
  51.  
  52. #define AUDIO_SUSPEND 1
  53. #define AUDIO_RESUME 2
  54. #define AUDIO_DIE 3
  55.  
  56. static volatile int audio_command=0, audio_response=0, bLocked=0, bInCallback=0;
  57.  
  58. static void audio_thread(void)
  59. {
  60.     SDL_printf("Audio_thread created\n");
  61.     int bPaused;
  62.     ksys_signal_info_t snd_signal;
  63.         // initialize
  64.     if (CreateBuffer(used_format|PCM_RING, 0, &hBuff)) {
  65.         audio_response=1;
  66.         exit(0);
  67.     }
  68.    
  69.     GetBufferSize(hBuff, &mix_size);
  70.     SDL_printf("buffer created, size is %d\n", mix_size);
  71.     mix_size >>= 1;
  72.     data = malloc(mix_size);
  73.     audio_response = 1;
  74.     if (!data) exit(0);
  75.    
  76.     // wait for resume
  77.     while (audio_command != AUDIO_RESUME)
  78.         _ksys_thread_yield();
  79.     audio_command = 0;
  80.     bPaused = 0;
  81.     audio_response = 1;
  82.     PlayBuffer(hBuff, 0);
  83.    
  84.     // main loop
  85.     while(1) {
  86.         if (audio_command == AUDIO_RESUME) {
  87.             PlayBuffer(hBuff, 0);
  88.             audio_command = 0;
  89.             bPaused = 0;
  90.             audio_response = 1;
  91.         } else if (audio_command == AUDIO_SUSPEND) {
  92.             StopBuffer(hBuff);
  93.             audio_command = 0;
  94.             bPaused = 1;
  95.             audio_response = 1;
  96.         }else if (audio_command == AUDIO_DIE) {
  97.             audio_response = 1;
  98.             StopBuffer(hBuff);
  99.             DestroyBuffer(hBuff);
  100.             exit(0);
  101.         } else {
  102.             _ksys_thread_info(&thread_info, main_slot);
  103.             if (thread_info.slot_state == KSYS_SLOT_STATE_FREE || thread_info.pid !=main_tid) {
  104.                 audio_command = AUDIO_DIE;
  105.                 continue;
  106.             }
  107.         }
  108.         if (bPaused) {
  109.             _ksys_delay(5);
  110.         } else {
  111.             _ksys_wait_signal(&snd_signal);
  112.             if (snd_signal.id != 0xFF000001)
  113.                 continue;
  114.             while (bLocked)
  115.                 _ksys_thread_yield();
  116.  
  117.             bInCallback=1;
  118.             callback(userdata, data, mix_size);
  119.             bInCallback=0;
  120.             SetBuffer(hBuff, data, ((int*)snd_signal.data)[2], mix_size);
  121.         }
  122.     }
  123. }
  124.  
  125. int SDL_OpenAudio(SDL_AudioSpec* desired, SDL_AudioSpec* obtained)
  126. {
  127.     if (!bInitialized) {
  128.         SDL_SetError("Audio device was not initialized");
  129.         return -1;
  130.     }
  131.    
  132.     if (!obtained) {
  133.         SDL_SetError("Audio format: software emulation is not supported");
  134.         return -1;
  135.     }
  136.        
  137.     if (used_format) {
  138.         SDL_SetError("Audio device was already opened");
  139.         return -1;
  140.     }
  141.     memcpy(obtained, desired, sizeof(SDL_AudioSpec));
  142.     switch (desired->freq) {
  143.  
  144. #define HANDLE_FREQ(freq,symb)                          \
  145.         case freq:                                      \
  146.                 switch (desired->channels)              \
  147.                 {                                       \
  148.                 case 1:                                 \
  149.                         switch (desired->format)        \
  150.                         {                               \
  151.                         case AUDIO_U8:                  \
  152.                         case AUDIO_S8:                  \
  153.                                 used_format = PCM_1_8_##symb;   \
  154.                                 break;                  \
  155.                         case AUDIO_U16SYS:              \
  156.                         case AUDIO_S16SYS:              \
  157.                                 used_format = PCM_1_16_##symb;  \
  158.                                 break;                  \
  159.                         }                               \
  160.                         break;                          \
  161.                 case 2:                                 \
  162.                         switch (desired->format)        \
  163.                         {                               \
  164.                         case AUDIO_U8:                  \
  165.                         case AUDIO_S8:                  \
  166.                                 used_format = PCM_2_8_##symb;   \
  167.                                 break;                  \
  168.                         case AUDIO_U16SYS:              \
  169.                         case AUDIO_S16SYS:              \
  170.                                 used_format = PCM_2_16_##symb;  \
  171.                                 break;                  \
  172.                         }                               \
  173.                         break;                          \
  174.                 }                                       \
  175.                 break;
  176.  
  177.         HANDLE_FREQ(48000,48);
  178.         HANDLE_FREQ(44100,44);
  179.         HANDLE_FREQ(32000,32);
  180.         HANDLE_FREQ(24000,24);
  181.         HANDLE_FREQ(22050,22);
  182.         HANDLE_FREQ(16000,16);
  183.         HANDLE_FREQ(12000,12);
  184.         HANDLE_FREQ(11025,11);
  185.         HANDLE_FREQ(8000,8);
  186.     }
  187.  
  188.     if (!used_format) {
  189.         SDL_SetError("Unknown audio format");
  190.         return -1;
  191.     }
  192.  
  193.     callback = desired->callback;
  194.     userdata = desired->userdata;
  195.        
  196.     _ksys_thread_info(&thread_info, KSYS_THIS_SLOT);
  197.     main_tid = thread_info.pid;
  198.     for (main_slot=0 ;; main_slot++) {
  199.         _ksys_thread_info(&thread_info, main_slot);
  200.         if (thread_info.slot_state != KSYS_SLOT_STATE_FREE && thread_info.pid == main_tid)
  201.             break;
  202.     }
  203.     audio_tid = _ksys_create_thread(audio_thread, audio_thread_stack+AUDIO_THREAD_STACK_SIZE);
  204.     if (audio_tid < 0) {
  205.         SDL_SetError("Cannot create audio thread");
  206.             return -1;
  207.     }
  208.    
  209.     _ksys_focus_window(main_slot);
  210.     while (!audio_response)
  211.         _ksys_thread_yield();
  212.    
  213.     if (!hBuff) {
  214.         SDL_SetError("Cannot create audio buffer");
  215.         return -1;
  216.     }
  217.     if (!data){
  218.         SDL_SetError("Cannot allocate audio buffer");
  219.         return -1;
  220.     }
  221.     obtained->silence = (desired->format == AUDIO_U8 ? 0x80 : 0);
  222.     obtained->size = mix_size;
  223.     obtained->samples = obtained->size / obtained->channels;
  224.        
  225.     if (desired->format == AUDIO_U16SYS || desired->format == AUDIO_S16SYS)
  226.         obtained->samples /= 2;
  227.    
  228.     SDL_printf("obtained size is %d, samples %d\n", obtained->size, obtained->samples);
  229.     return 0;
  230. }
  231. void SDL_CloseAudio(void)
  232. {
  233.     if (!audio_tid) return;
  234.     audio_response = 0;
  235.     audio_command = AUDIO_DIE;
  236.     while (!audio_response) _ksys_thread_yield();
  237.     free(data);
  238.     used_format = 0;
  239. }
  240.  
  241. void SDL_PauseAudio(int pause_on)
  242. {
  243.     if (!audio_tid) return;
  244.     audio_response = 0;
  245.     audio_command = pause_on ? AUDIO_SUSPEND : AUDIO_RESUME;
  246.     while (!audio_response) _ksys_thread_yield();
  247. }
  248. void SDL_LockAudio(void)
  249. {
  250.     if (!audio_tid) return;
  251.     bLocked = 1;
  252.     while (bInCallback) _ksys_thread_yield();
  253. }
  254. void SDL_UnlockAudio(void)
  255. {
  256.     bLocked = 0;
  257. }
  258.