Advertisement
Guest User

Untitled

a guest
May 26th, 2018
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.98 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. typedef struct
  32. {
  33. audio_output_t output;
  34. handle_t event;
  35. audio_output_buffer_t buffers[3];
  36. audio_output_buffer_t *current_buffer;
  37. bool blocking;
  38. bool is_paused;
  39. bool pages_initialized;
  40. uint64_t last_append;
  41. unsigned latency;
  42. } switch_audio_t;
  43.  
  44. static ssize_t switch_audio_write(void *data, const void *buf, size_t size)
  45. {
  46. size_t to_write = size;
  47. switch_audio_t *swa = (switch_audio_t*) data;
  48.  
  49. #if 0
  50. RARCH_LOG("write %ld samples\n", size/sizeof(uint16_t));
  51. #endif
  52.  
  53. if (!swa->current_buffer)
  54. {
  55. uint32_t num;
  56.  
  57. if (swa->pages_initialized && audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK)
  58. {
  59. RARCH_LOG("Failed to get released buffer?\n");
  60. return -1;
  61. } else {
  62. for(int i = 0; i < 3; i++)
  63. {
  64. swa->buffers[i].ptr = &swa->buffers[i].sample_data;
  65. swa->buffers[i].sample_data = alloc_pages(sample_buffer_size, sample_buffer_size, NULL);
  66. swa->buffers[i].buffer_size = sample_buffer_size;
  67. swa->buffers[i].data_size = sample_buffer_size;
  68. swa->buffers[i].unknown = 0;
  69.  
  70. // audio_ipc_output_append_buffer(&swa->output, &swa->buffers[i]);
  71. }
  72.  
  73. num = 1;
  74. swa->pages_initialized = true;
  75. }
  76. #if 0
  77. RARCH_LOG("got buffer, num %d, ptr %p\n", num, swa->current_buffer);
  78. #endif
  79.  
  80. if (num < 1)
  81. swa->current_buffer = NULL;
  82.  
  83. if (!swa->current_buffer)
  84. {
  85. if (swa->blocking)
  86. {
  87. RARCH_LOG("No buffer, blocking...\n");
  88.  
  89. while(swa->current_buffer == NULL)
  90. {
  91. uint32_t num;
  92. uint32_t handle_idx;
  93.  
  94. svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333);
  95. svcResetSignal(swa->event);
  96.  
  97. if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK)
  98. return -1;
  99. }
  100. } else {
  101. /* no buffer, nonblocking... */
  102. return 0;
  103. }
  104. }
  105.  
  106. swa->current_buffer->data_size = 0;
  107. }
  108.  
  109. if (to_write > sample_buffer_size - swa->current_buffer->data_size)
  110. to_write = sample_buffer_size - swa->current_buffer->data_size;
  111.  
  112. memcpy(((uint8_t*) swa->current_buffer->sample_data) + swa->current_buffer->data_size, buf, to_write);
  113. swa->current_buffer->data_size += to_write;
  114. swa->current_buffer->buffer_size = sample_buffer_size;
  115.  
  116. if (swa->current_buffer->data_size > (48000*swa->latency)/1000)
  117. {
  118. result_t r = audio_ipc_output_append_buffer(&swa->output, swa->current_buffer);
  119. if (r != RESULT_OK)
  120. {
  121. RARCH_ERR("failed to append buffer: 0x%x\n", r);
  122. return -1;
  123. }
  124. swa->current_buffer = NULL;
  125. }
  126.  
  127. #if 0
  128. RARCH_LOG("submitted %ld samples, %ld samples since last submit\n",
  129. to_write/num_channels/sizeof(uint16_t),
  130. (svcGetSystemTick() - swa->last_append) * sample_rate / 19200000);
  131. #endif
  132. swa->last_append = svcGetSystemTick();
  133.  
  134. return to_write;
  135. }
  136.  
  137. static bool switch_audio_stop(void *data)
  138. {
  139. switch_audio_t *swa = (switch_audio_t*) data;
  140. if (!swa)
  141. return false;
  142.  
  143. if(!swa->is_paused) {
  144. if(audio_ipc_output_stop(&swa->output) != RESULT_OK)
  145. return false;
  146. }
  147.  
  148. swa->is_paused = true;
  149. return true;
  150. }
  151.  
  152. static bool switch_audio_start(void *data, bool is_shutdown)
  153. {
  154. switch_audio_t *swa = (switch_audio_t*) data;
  155.  
  156. if(swa->is_paused) {
  157. if (audio_ipc_output_start(&swa->output) != RESULT_OK)
  158. return false;
  159. }
  160.  
  161. swa->is_paused = false;
  162. return true;
  163. }
  164.  
  165. static bool switch_audio_alive(void *data)
  166. {
  167. switch_audio_t *swa = (switch_audio_t*) data;
  168. if (!swa)
  169. return false;
  170. return !swa->is_paused;
  171. }
  172.  
  173. static void switch_audio_free(void *data)
  174. {
  175. switch_audio_t *swa = (switch_audio_t*) data;
  176.  
  177. audio_ipc_output_close(&swa->output);
  178. audio_ipc_finalize();
  179. free(swa);
  180. }
  181.  
  182. static bool switch_audio_use_float(void *data)
  183. {
  184. (void) data;
  185. return false; /* force INT16 */
  186. }
  187.  
  188. static size_t switch_audio_write_avail(void *data)
  189. {
  190. switch_audio_t *swa = (switch_audio_t*) data;
  191.  
  192. if (!swa || !swa->current_buffer)
  193. return 0;
  194.  
  195. return swa->current_buffer->buffer_size;
  196. }
  197.  
  198. static void switch_audio_set_nonblock_state(void *data, bool state)
  199. {
  200. switch_audio_t *swa = (switch_audio_t*) data;
  201.  
  202. if (swa)
  203. swa->blocking = !state;
  204. }
  205.  
  206. static void *switch_audio_init(const char *device,
  207. unsigned rate, unsigned latency,
  208. unsigned block_frames,
  209. unsigned *new_rate)
  210. {
  211. result_t r;
  212. unsigned i;
  213. char names[8][0x20];
  214. uint32_t num_names = 0;
  215. switch_audio_t *swa = (switch_audio_t*) calloc(1, sizeof(*swa));
  216.  
  217. if (!swa)
  218. return NULL;
  219.  
  220. r = audio_ipc_init();
  221.  
  222. if (r != RESULT_OK)
  223. goto fail;
  224.  
  225. if (audio_ipc_list_outputs(&names[0], 8, &num_names) != RESULT_OK)
  226. goto fail_audio_ipc;
  227.  
  228. if (num_names != 1)
  229. {
  230. RARCH_ERR("got back more than one AudioOut\n");
  231. goto fail_audio_ipc;
  232. }
  233.  
  234. if (audio_ipc_open_output(names[0], &swa->output) != RESULT_OK)
  235. goto fail_audio_ipc;
  236.  
  237. if (swa->output.sample_rate != sample_rate)
  238. {
  239. RARCH_ERR("expected sample rate of %d, got sample rate of %d\n",
  240. sample_rate, swa->output.sample_rate);
  241. goto fail_audio_output;
  242. }
  243.  
  244. if (swa->output.num_channels != num_channels)
  245. {
  246. RARCH_ERR("expected %d channels, got %d\n", num_channels,
  247. swa->output.num_channels);
  248. goto fail_audio_output;
  249. }
  250.  
  251. if (swa->output.sample_format != PCM_INT16)
  252. {
  253. RARCH_ERR("expected PCM_INT16, got %d\n", swa->output.sample_format);
  254. goto fail_audio_output;
  255. }
  256.  
  257. if (audio_ipc_output_register_buffer_event(&swa->output, &swa->event) != RESULT_OK)
  258. goto fail_audio_output;
  259.  
  260. swa->blocking = block_frames;
  261. *new_rate = swa->output.sample_rate;
  262. swa->current_buffer = NULL;
  263. swa->latency = latency;
  264. swa->last_append = svcGetSystemTick();
  265.  
  266. swa->is_paused = true;
  267.  
  268. return swa;
  269.  
  270. fail_audio_output:
  271. audio_ipc_output_close(&swa->output);
  272. fail_audio_ipc:
  273. audio_ipc_finalize();
  274. fail:
  275. free(swa);
  276. return NULL;
  277. }
  278.  
  279. static size_t switch_audio_buffer_size(void *data)
  280. {
  281. (void) data;
  282. return sample_buffer_size;
  283. }
  284.  
  285. audio_driver_t audio_switch = {
  286. switch_audio_init,
  287. switch_audio_write,
  288. switch_audio_stop,
  289. switch_audio_start,
  290. switch_audio_alive,
  291. switch_audio_set_nonblock_state,
  292. switch_audio_free,
  293. switch_audio_use_float,
  294. "switch",
  295. NULL, /* device_list_new */
  296. NULL, /* device_list_free */
  297. switch_audio_write_avail,
  298. switch_audio_buffer_size, /* buffer_size */
  299. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement