main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #include "../headers/yuzuparse.h"
  2. int (*cprintf)(const char *__restrict __format, ...) = printf;
  3. int printf_override(const char *__restrict __format, ...){
  4. return 0;
  5. }
  6. #define print (*cprintf)
  7. char* lsb_byte_to_binary(uint32_t byte, uint8_t bits){
  8. char* string = malloc(sizeof(char) * (bits + 1));
  9. for (int i = 0; i < bits; i++){
  10. string[i] = ((byte >> i) & 1) + 0x30;
  11. }
  12. string[bits] = '\0';
  13. return string;
  14. }
  15. // MSB, most sig bit is first
  16. // 1 = 00000001
  17. char* msb_byte_to_binary(uint32_t byte, uint8_t bits){
  18. char* string = malloc(sizeof(char) * (bits + 1));
  19. for (int i = 0; i < bits; i++){
  20. string[bits - 1 - i] = ((byte >> i) & 1) + 0x30;
  21. }
  22. string[bits] = '\0';
  23. return string;
  24. }
  25. // MSB, most sig bit is first
  26. // 1 = 00000001
  27. uint16_t binary_to_int(char* binary, uint8_t number_of_bits){
  28. uint16_t final_value = 0;
  29. for (int i = 0; i < number_of_bits; i++){
  30. final_value += (1 << i) * (binary[number_of_bits - i - 1] - 0x30);
  31. }
  32. return final_value;
  33. }
  34. // return individial bit's value. Zero indexed
  35. // msb_get_bit(00100, 2) == 1
  36. uint8_t msb_get_bit(uint32_t data, uint8_t bit){
  37. return (data >> bit) & 1;
  38. }
  39. uint32_t current_byte = 0;
  40. uint8_t* file_buffer = NULL;
  41. // byte reading funcs
  42. void skip(int bytes_to_skip){
  43. current_byte += bytes_to_skip;
  44. }
  45. int8_t get_1(){
  46. return file_buffer[current_byte++];
  47. }
  48. int16_t get_2(){
  49. int16_t result = file_buffer[current_byte] | (file_buffer[current_byte + 1] << 8);
  50. current_byte += 2;
  51. return result;
  52. }
  53. int32_t get_4(){
  54. int32_t result = file_buffer[current_byte] |
  55. (file_buffer[current_byte + 1] << 8) |
  56. (file_buffer[current_byte + 2] << 16) |
  57. (file_buffer[current_byte + 3] << 24);
  58. current_byte += 4;
  59. return result;
  60. }
  61. YZ_audio_stream* YZ_load_wav(){
  62. YZ_audio_stream* audio_stream = malloc(sizeof(YZ_audio_stream));
  63. char filename[5] = {get_1(), get_1(), get_1(), get_1(), '\0'};
  64. if (strcmp(filename, "RIFF")){
  65. printf("file is not a WAVE file\n");
  66. return NULL;
  67. }
  68. uint32_t chunk_size = get_4();
  69. char wave_id[5] = {get_1(), get_1(), get_1(), get_1(), '\0'};
  70. unsigned char reading_file = 1;
  71. uint32_t chunk_id;
  72. uint16_t bits_per_sample;
  73. uint16_t data_block_size;
  74. skip(4);
  75. print("reading format chunk at byte #%d\n", current_byte - 4);
  76. uint32_t fmt_chunk_size = get_4();
  77. uint16_t format_code = get_2();
  78. uint16_t interleaved_channel_count = get_2();
  79. uint32_t samples_per_second = get_4(); // blocks per second
  80. uint32_t bytes_per_second = get_4();
  81. data_block_size = get_2();
  82. bits_per_sample = get_2();
  83. uint16_t extension_size = 0;
  84. if (fmt_chunk_size > 16) extension_size = get_2();
  85. uint16_t valid_bits_per_sample = 0;
  86. if (fmt_chunk_size > 18) valid_bits_per_sample = get_2();
  87. if (fmt_chunk_size != 16){
  88. printf("audio data is not PCM. cannot read this yet\n");
  89. return NULL;
  90. }
  91. if (format_code != 1){
  92. printf("audio data is compressed. cannot read this yet\n");
  93. return NULL;
  94. }
  95. audio_stream->channel_count = interleaved_channel_count;
  96. audio_stream->sample_rate = (double)samples_per_second;
  97. print("fmt_chunk_size: %d\nformat_code: %d\ninterleaved_channel_count: %d\nsamples_per_second: %d\nbytes_per_second: %d\ndata_block_size: %d\nbits_per_sample: %d\nextension_size: %d\nvalid_bits_per_sample: %d\n", fmt_chunk_size, format_code, interleaved_channel_count, samples_per_second, bytes_per_second, data_block_size, bits_per_sample, extension_size, valid_bits_per_sample);
  98. // data
  99. while (get_4() != 1635017060)
  100. current_byte -= 3;
  101. print("reading data chunk at byte #%d\n", current_byte - 4);
  102. uint32_t data_chunk_size = get_4();
  103. audio_stream->pcm_data = malloc(sizeof(double) * (data_chunk_size / (bits_per_sample / 8)));
  104. audio_stream->sample_count = data_chunk_size / (bits_per_sample / 8) / audio_stream->channel_count;
  105. print("data chunk is %d bytes\n", data_chunk_size);
  106. uint32_t current_sample = 0;
  107. for (uint32_t i = 0; i < data_chunk_size;){
  108. uint32_t sample_index = current_sample++ * audio_stream->channel_count;
  109. uint32_t bytes_read = 0;
  110. for (uint32_t j = 0; j < audio_stream->channel_count; j++){
  111. double value;
  112. if (bits_per_sample == 8){
  113. value = ((double)get_1() - 128.0) / 128.0;
  114. bytes_read += 1;
  115. } else if (bits_per_sample == 16){
  116. value = (double)(int16_t)get_2() / 32768.0;
  117. bytes_read += 2;
  118. } else if (bits_per_sample == 32){
  119. printf("cannot read 32 bit per sample audio yet\n");
  120. return NULL;
  121. }
  122. audio_stream->pcm_data[sample_index + j] = value;
  123. }
  124. i += bytes_read;
  125. }
  126. return audio_stream;
  127. }
  128. YZ_audio_stream* YZ_load_mp3(){return NULL;}
  129. YZ_audio_stream* YZ_load_ogg(){return NULL;}
  130. YZ_audio_stream* YZ_load_flac(){return NULL;}
  131. YZ_audio_stream* YZ_load_aiff(){return NULL;}
  132. YZ_audio_stream* YZ_load_audio_file(char* filename, unsigned char debug_mode){
  133. FILE *fp = fopen(filename, "rb");
  134. if (fp == NULL){
  135. printf("file \"%s\" does not exist !!!\n", filename);
  136. return NULL;
  137. }
  138. fseek(fp, 0, SEEK_END);
  139. long size = ftell(fp);
  140. rewind(fp);
  141. file_buffer = malloc(size);
  142. fread(file_buffer, 1, size, fp);
  143. fclose(fp);
  144. // override (*cprintf) so there is no debug output
  145. if (!debug_mode){
  146. cprintf = printf_override;
  147. }
  148. // see what the file type is
  149. char* mutable_filename = malloc(sizeof(char) * (strlen(filename) + 1));
  150. strcpy(mutable_filename, filename);
  151. char *strtok_string = strtok(mutable_filename, ".");
  152. char *filetype_string;
  153. while(strtok_string != NULL) {
  154. filetype_string = strtok_string;
  155. strtok_string = strtok(NULL, ".");
  156. }
  157. current_byte = 0;
  158. if (!strcmp(filetype_string, "wav") || !strcmp(filetype_string, "WAV") || !strcmp(filetype_string, "wave") || !strcmp(filetype_string, "WAVE")){
  159. return YZ_load_wav();
  160. } else
  161. if (!strcmp(filetype_string, "mp3") || !strcmp(filetype_string, "MP3") || !strcmp(filetype_string, "mpga") || !strcmp(filetype_string, "MPGA")){
  162. return YZ_load_mp3();
  163. } else
  164. if (!strcmp(filetype_string, "placeholder") || !strcmp(filetype_string, "placeholder")){
  165. return YZ_load_ogg();
  166. } else
  167. if (!strcmp(filetype_string, "placeholder") || !strcmp(filetype_string, "placeholder")){
  168. return YZ_load_flac();
  169. } else
  170. if (!strcmp(filetype_string, "placeholder") || !strcmp(filetype_string, "placeholder")){
  171. return YZ_load_aiff();
  172. }
  173. (*cprintf)("file is unreadable by Yuzu\n");
  174. return NULL;
  175. }
  176. int portaudio_callback(const void* input, void* output, unsigned long frame_count, const PaStreamCallbackTimeInfo* pa_time_info, PaStreamCallbackFlags pa_status_flags, void* audio_data){
  177. pa_callback_data* data = (pa_callback_data*)audio_data;
  178. float* out = (float*)output;
  179. for(uint32_t i = 0; i < frame_count; i++){
  180. for (uint32_t j = 0; j < data->channel_count; j++) {
  181. *out++ = data->pcm_data[(int)(data->current_sample) * data->channel_count + j];
  182. }
  183. data->current_sample += *data->speed_multiplier;
  184. if (*data->should_loop_audio){
  185. if (data->current_sample >= data->sample_count){
  186. data->current_sample = data->sample_count - data->current_sample;
  187. } else if (data->current_sample < 0){
  188. data->current_sample = data->sample_count + data->current_sample;
  189. }
  190. }
  191. if (data->current_sample >= data->sample_count || data->current_sample < 0){
  192. goto END;
  193. }
  194. }
  195. if (data->current_sample >= data->sample_count){
  196. goto END;
  197. }
  198. return 0;
  199. END:
  200. if (data->end_function) data->end_function(data->custom_pointer_for_end_function);
  201. free(audio_data);
  202. return 1;
  203. }
  204. unsigned char player_is_initialized = 0;
  205. void YZ_init_player(){
  206. if (player_is_initialized){
  207. printf("cannot init, already started");
  208. return;
  209. }
  210. PaError error;
  211. // block PortAudio's standard output and standard error stream
  212. freopen("/dev/null", "w", stdout);
  213. freopen("/dev/null", "w", stderr);
  214. error = Pa_Initialize();
  215. // unblock PortAudio's standard output and standard error stream
  216. freopen("/dev/tty", "w", stdout);
  217. freopen("/dev/tty", "w", stderr);
  218. if(error != paNoError) { printf("PortAudio error: %d\n", error); exit(1);}
  219. player_is_initialized = 1;
  220. }
  221. void YZ_kill_player(){
  222. if (!player_is_initialized){
  223. printf("cannot kill, player isn't initilized");
  224. return;
  225. }
  226. PaError error;
  227. error = Pa_Terminate();
  228. if(error != paNoError) { printf("PortAudio error: %d\n", error); exit(1);}
  229. }
  230. pa_callback_data* play_stream(YZ_audio_stream* audio_stream, double* pitch_multiplier, double* speed_multiplier, unsigned char* should_loop_audio, double starting_second, void (*end_func)(void* custom_pointer_for_end_function), void* custom_pointer_for_end_function){
  231. PaError error;
  232. PaStream *stream;
  233. pa_callback_data* callback_data = malloc(sizeof(pa_callback_data));
  234. callback_data->channel_count = audio_stream->channel_count;
  235. callback_data->current_sample = starting_second >= 0 ? audio_stream->sample_rate * starting_second : audio_stream->sample_count;
  236. callback_data->pcm_data = audio_stream->pcm_data;
  237. callback_data->sample_count = audio_stream->sample_count;
  238. callback_data->pitch_multiplier = pitch_multiplier;
  239. callback_data->speed_multiplier = speed_multiplier;
  240. callback_data->should_loop_audio = should_loop_audio;
  241. callback_data->end_function = end_func;
  242. callback_data->custom_pointer_for_end_function = custom_pointer_for_end_function;
  243. if (!player_is_initialized) YZ_init_player();
  244. error = Pa_OpenDefaultStream(&stream, 0, audio_stream->channel_count, paFloat32, audio_stream->sample_rate, paFramesPerBufferUnspecified, portaudio_callback, callback_data);
  245. if(error != paNoError) { printf("PortAudio error: %d\n", error); exit(1);}
  246. Pa_StartStream(stream);
  247. return callback_data;
  248. }
  249. // play an audio stream
  250. pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream){
  251. double value = 1;
  252. unsigned char antivalue = 0;
  253. return play_stream(audio_stream, &value, &value, &antivalue, (double)antivalue, NULL, NULL);
  254. }
  255. // play an audio stream and modify pitch and speed dynamically. Pitch and speed changes work in real time due to it being pointers to the values
  256. pa_callback_data* YZ_play_stream_dynamic(YZ_audio_stream* audio_stream, double* speed_multiplier, unsigned char* should_loop_audio, double starting_second, void (*end_func)(void*), void* custom_pointer_for_end_function){
  257. return play_stream(audio_stream, NULL, speed_multiplier, should_loop_audio, starting_second, end_func, custom_pointer_for_end_function);
  258. }