Guest User

Untitled

a guest
May 26th, 2018
506
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.15 KB | None | 0 0
  1. /* RetroArch - A frontend for libretro.
  2. *
  3. * RetroArch is free software: you can redistribute it and/or modify it under the terms
  4. * of the GNU General Public License as published by the Free Software Found-
  5. * ation, either version 3 of the License, or (at your option) any later version.
  6. *
  7. * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  8. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  9. * PURPOSE. See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with RetroArch.
  12. * If not, see <http://www.gnu.org/licenses/>.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <malloc.h>
  18. #include <stdint.h>
  19.  
  20. #include<libtransistor/nx.h>
  21. #include<libtransistor/alloc_pages.h>
  22.  
  23. #include "../audio_driver.h"
  24. #include "../../verbosity.h"
  25.  
  26. static const int sample_rate = 48000;
  27. static const int max_num_samples = sample_rate;
  28. static const int num_channels = 2;
  29. static const size_t sample_buffer_size = ((max_num_samples * num_channels * sizeof(uint16_t)) + 0xfff) & ~0xfff;
  30.  
  31. #define num_frames_per_chunk (48000 / 35)
  32. static const size_t chunk_size = ((num_frames_per_chunk * sizeof(uint32_t)) + 0xfff) & ~0xfff;
  33. static uint32_t __attribute__((aligned(0x1000))) chunks[3][chunk_size / sizeof(uint32_t)];
  34.  
  35. typedef struct
  36. {
  37. audio_output_t output;
  38. handle_t event;
  39. audio_output_buffer_t buffers[3];
  40. audio_output_buffer_t *current_buffer;
  41. bool blocking;
  42. bool is_paused;
  43. uint64_t last_append;
  44. unsigned latency;
  45. } switch_audio_t;
  46.  
  47. static ssize_t switch_audio_write(void *data, const void *buf, size_t size)
  48. {
  49. size_t to_write = size;
  50. switch_audio_t *swa = (switch_audio_t*) data;
  51.  
  52. #if 0
  53. RARCH_LOG("write %ld samples\n", size/sizeof(uint16_t));
  54. #endif
  55.  
  56. if (!swa->current_buffer)
  57. {
  58. uint32_t num;
  59. if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK)
  60. {
  61. RARCH_LOG("Failed to get released buffer?\n");
  62. return -1;
  63. }
  64.  
  65. #if 0
  66. RARCH_LOG("got buffer, num %d, ptr %p\n", num, swa->current_buffer);
  67. #endif
  68.  
  69. if (num < 1)
  70. swa->current_buffer = NULL;
  71.  
  72. if (!swa->current_buffer)
  73. {
  74. if (swa->blocking)
  75. {
  76. RARCH_LOG("No buffer, blocking...\n");
  77.  
  78. while(swa->current_buffer == NULL)
  79. {
  80. uint32_t num;
  81. uint32_t handle_idx;
  82.  
  83. svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333);
  84. svcResetSignal(swa->event);
  85.  
  86. if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK)
  87. return -1;
  88. }
  89. } else {
  90. /* no buffer, nonblocking... */
  91. return 0;
  92. }
  93. }
  94.  
  95. swa->current_buffer->data_size = 0;
  96. }
  97.  
  98. if (to_write > sample_buffer_size - swa->current_buffer->data_size)
  99. to_write = sample_buffer_size - swa->current_buffer->data_size;
  100.  
  101. memcpy(((uint8_t*) swa->current_buffer->sample_data) + swa->current_buffer->data_size, buf, to_write);
  102. swa->current_buffer->data_size += to_write;
  103. swa->current_buffer->buffer_size = sample_buffer_size;
  104.  
  105. if (swa->current_buffer->data_size > (48000*swa->latency)/1000)
  106. {
  107. result_t r = audio_ipc_output_append_buffer(&swa->output, swa->current_buffer);
  108. if (r != RESULT_OK)
  109. {
  110. RARCH_ERR("failed to append buffer: 0x%x\n", r);
  111. return -1;
  112. }
  113. swa->current_buffer = NULL;
  114. }
  115.  
  116. #if 0
  117. RARCH_LOG("submitted %ld samples, %ld samples since last submit\n",
  118. to_write/num_channels/sizeof(uint16_t),
  119. (svcGetSystemTick() - swa->last_append) * sample_rate / 19200000);
  120. #endif
  121. swa->last_append = svcGetSystemTick();
  122.  
  123. return to_write;
  124. }
  125.  
  126. static bool switch_audio_stop(void *data)
  127. {
  128. switch_audio_t *swa = (switch_audio_t*) data;
  129. if (!swa)
  130. return false;
  131.  
  132. if(!swa->is_paused) {
  133. if(audio_ipc_output_stop(&swa->output) != RESULT_OK)
  134. return false;
  135. }
  136.  
  137. swa->is_paused = true;
  138. return true;
  139. }
  140.  
  141. static bool switch_audio_start(void *data, bool is_shutdown)
  142. {
  143. switch_audio_t *swa = (switch_audio_t*) data;
  144.  
  145. if(swa->is_paused) {
  146. if (audio_ipc_output_start(&swa->output) != RESULT_OK)
  147. return false;
  148. }
  149.  
  150. swa->is_paused = false;
  151. return true;
  152. }
  153.  
  154. static bool switch_audio_alive(void *data)
  155. {
  156. switch_audio_t *swa = (switch_audio_t*) data;
  157. if (!swa)
  158. return false;
  159. return !swa->is_paused;
  160. }
  161.  
  162. static void switch_audio_free(void *data)
  163. {
  164. switch_audio_t *swa = (switch_audio_t*) data;
  165.  
  166. audio_ipc_output_close(&swa->output);
  167. audio_ipc_finalize();
  168. free(swa);
  169. }
  170.  
  171. static bool switch_audio_use_float(void *data)
  172. {
  173. (void) data;
  174. return false; /* force INT16 */
  175. }
  176.  
  177. static size_t switch_audio_write_avail(void *data)
  178. {
  179. switch_audio_t *swa = (switch_audio_t*) data;
  180.  
  181. if (!swa || !swa->current_buffer)
  182. return 0;
  183.  
  184. return swa->current_buffer->buffer_size;
  185. }
  186.  
  187. static void switch_audio_set_nonblock_state(void *data, bool state)
  188. {
  189. switch_audio_t *swa = (switch_audio_t*) data;
  190.  
  191. if (swa)
  192. swa->blocking = !state;
  193. }
  194.  
  195. static void *switch_audio_init(const char *device,
  196. unsigned rate, unsigned latency,
  197. unsigned block_frames,
  198. unsigned *new_rate)
  199. {
  200. result_t r;
  201. unsigned i;
  202. char names[8][0x20];
  203. uint32_t num_names = 0;
  204. switch_audio_t *swa = (switch_audio_t*) calloc(1, sizeof(*swa));
  205.  
  206. if (!swa)
  207. return NULL;
  208.  
  209. r = audio_ipc_init();
  210.  
  211. if (r != RESULT_OK)
  212. goto fail;
  213.  
  214. if (audio_ipc_list_outputs(&names[0], 8, &num_names) != RESULT_OK)
  215. goto fail_audio_ipc;
  216.  
  217. if (num_names != 1)
  218. {
  219. RARCH_ERR("got back more than one AudioOut\n");
  220. goto fail_audio_ipc;
  221. }
  222.  
  223. if (audio_ipc_open_output(names[0], &swa->output) != RESULT_OK)
  224. goto fail_audio_ipc;
  225.  
  226. if (swa->output.sample_rate != sample_rate)
  227. {
  228. RARCH_ERR("expected sample rate of %d, got sample rate of %d\n",
  229. sample_rate, swa->output.sample_rate);
  230. goto fail_audio_output;
  231. }
  232.  
  233. if (swa->output.num_channels != num_channels)
  234. {
  235. RARCH_ERR("expected %d channels, got %d\n", num_channels,
  236. swa->output.num_channels);
  237. goto fail_audio_output;
  238. }
  239.  
  240. if (swa->output.sample_format != PCM_INT16)
  241. {
  242. RARCH_ERR("expected PCM_INT16, got %d\n", swa->output.sample_format);
  243. goto fail_audio_output;
  244. }
  245.  
  246. if (audio_ipc_output_register_buffer_event(&swa->output, &swa->event) != RESULT_OK)
  247. goto fail_audio_output;
  248.  
  249. swa->blocking = block_frames;
  250.  
  251. *new_rate = swa->output.sample_rate;
  252.  
  253. for(i = 0; i < 3; i++)
  254. {
  255. swa->buffers[i].ptr = &swa->buffers[i].sample_data;
  256. swa->buffers[i].sample_data = chunks[i];
  257. swa->buffers[i].buffer_size = sizeof(chunks[i]);
  258. swa->buffers[i].data_size = num_frames_per_chunk * sizeof(uint32_t);
  259. swa->buffers[i].unknown = 0;
  260.  
  261. if(swa->buffers[i].sample_data == NULL)
  262. goto fail_audio_output;
  263.  
  264. if (audio_ipc_output_append_buffer(&swa->output, &swa->buffers[i]) != RESULT_OK)
  265. goto fail_audio_output;
  266. }
  267.  
  268. swa->current_buffer = NULL;
  269. swa->latency = latency;
  270. swa->last_append = svcGetSystemTick();
  271.  
  272. swa->is_paused = true;
  273.  
  274. return swa;
  275.  
  276. fail_audio_output:
  277. audio_ipc_output_close(&swa->output);
  278. fail_audio_ipc:
  279. audio_ipc_finalize();
  280. fail:
  281. free(swa);
  282. return NULL;
  283. }
  284.  
  285. static size_t switch_audio_buffer_size(void *data)
  286. {
  287. (void) data;
  288. return sample_buffer_size;
  289. }
  290.  
  291. audio_driver_t audio_switch = {
  292. switch_audio_init,
  293. switch_audio_write,
  294. switch_audio_stop,
  295. switch_audio_start,
  296. switch_audio_alive,
  297. switch_audio_set_nonblock_state,
  298. switch_audio_free,
  299. switch_audio_use_float,
  300. "switch",
  301. NULL, /* device_list_new */
  302. NULL, /* device_list_free */
  303. switch_audio_write_avail,
  304. switch_audio_buffer_size, /* buffer_size */
  305. };
Advertisement
Add Comment
Please, Sign In to add comment