audio.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /* MegaZeux
  2. *
  3. * Copyright (C) 2008 Alan Williams <mralert@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include "../../src/audio/audio.h"
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <malloc.h>
  23. #define BOOL _BOOL
  24. #include <asndlib.h>
  25. #include <gctypes.h>
  26. #include <ogc/lwp.h>
  27. #include <ogc/cache.h>
  28. #include <ogc/system.h>
  29. #undef BOOL
  30. #define STACKSIZE 8192
  31. static lwpq_t audio_queue;
  32. static lwp_t audio_thread;
  33. static u8 audio_stack[STACKSIZE];
  34. static Sint16 *audio_buffer[3];
  35. static volatile int current = 0;
  36. static volatile int audio_stop = 0;
  37. static int buffer_size;
  38. static void *wii_audio_thread(void *dud)
  39. {
  40. while(!audio_stop)
  41. {
  42. LWP_ThreadSleep(audio_queue);
  43. audio_callback(audio_buffer[current], buffer_size);
  44. DCFlushRange(audio_buffer[current], buffer_size);
  45. current = (current + 1) % 3;
  46. }
  47. return 0;
  48. }
  49. static void voice_callback(s32 voice)
  50. {
  51. ASND_AddVoice(voice, audio_buffer[(current + 2) % 3], buffer_size);
  52. LWP_ThreadSignal(audio_queue);
  53. }
  54. void init_audio_platform(struct config_info *conf)
  55. {
  56. int i;
  57. // buffer size must be multiple of 32 bytes, so samples must be multiple of 8
  58. audio.buffer_samples = conf->audio_buffer_samples & ~7;
  59. if(!audio.buffer_samples)
  60. audio.buffer_samples = 2048;
  61. buffer_size = sizeof(Sint16) * 2 * audio.buffer_samples;
  62. audio.mix_buffer = malloc(buffer_size * 2);
  63. for(i = 0; i < 3; i++)
  64. {
  65. audio_buffer[i] = memalign(32, buffer_size);
  66. memset(audio_buffer[i], 0, buffer_size);
  67. DCFlushRange(audio_buffer[i], buffer_size);
  68. }
  69. ASND_Init();
  70. LWP_InitQueue(&audio_queue);
  71. if(LWP_CreateThread(&audio_thread, wii_audio_thread, NULL, audio_stack,
  72. STACKSIZE, 80) >= 0)
  73. {
  74. ASND_SetVoice(0, VOICE_STEREO_16BIT, audio.output_frequency, 0,
  75. audio_buffer[0], buffer_size, 255, 255, voice_callback);
  76. ASND_Pause(0);
  77. }
  78. }
  79. void quit_audio_platform(void)
  80. {
  81. void *dud;
  82. if(!audio.mix_buffer)
  83. return;
  84. audio_stop = 1;
  85. LWP_JoinThread(audio_thread, &dud);
  86. ASND_Pause(1);
  87. ASND_End();
  88. free(audio.mix_buffer);
  89. LWP_CloseQueue(audio_queue);
  90. // Don't free hardware audio buffers
  91. // Memory allocated with memalign() can't neccessarily be free()'d
  92. }