The "GR-PEACH_Audio_Playback_7InchLCD_Sample" is a sample code that can provides high-resolution audio playback of FLAC format files. It also allows the user to audio-playback control functions such as play, pause, and stop by manipulating key switches.
Dependencies: GR-PEACH_video R_BSP TLV320_RBSP USBHost_custom
Fork of GR-PEACH_Audio_Playback_Sample by
decode.cpp
00001 /******************************************************************************* 00002 * DISCLAIMER 00003 * This software is supplied by Renesas Electronics Corporation and is only 00004 * intended for use with Renesas products. No other uses are authorized. This 00005 * software is owned by Renesas Electronics Corporation and is protected under 00006 * all applicable laws, including copyright laws. 00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING 00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT 00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. 00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS 00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE 00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR 00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE 00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00016 * Renesas reserves the right, without notice, to make changes to this software 00017 * and to discontinue the availability of this software. By using this software, 00018 * you agree to the additional terms and conditions found by accessing the 00019 * following link: 00020 * http://www.renesas.com/disclaimer* 00021 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved. 00022 *******************************************************************************/ 00023 00024 #include "mbed.h" 00025 #include "rtos.h" 00026 #include "misratypes.h" 00027 #include "r_errno.h" 00028 #include "system.h" 00029 #include "decode.h" 00030 #include "audio_out.h" 00031 #include "dec_flac.h" 00032 00033 /*--- Macro definition of mbed-rtos mail ---*/ 00034 #define MAIL_QUEUE_SIZE (12) /* Queue size */ 00035 #define MAIL_PARAM_NUM (2) /* Elements number of mail parameter array */ 00036 00037 /* dec_mail_t */ 00038 #define MAIL_PARAM0 (0) /* Index number of mail parameter array */ 00039 #define MAIL_PARAM1 (1) /* Index number of mail parameter array */ 00040 00041 #define MAIL_PARAM_NON (0u) /* Value of unused element of mail parameter array */ 00042 00043 /* mail_id = DEC_MAILID_OPEN */ 00044 #define MAIL_OPEN_CB (MAIL_PARAM0) /* Callback function */ 00045 #define MAIL_OPEN_FILE (MAIL_PARAM1) /* File handle */ 00046 00047 /* mail_id = DEC_MAILID_PLAY : No parameter */ 00048 00049 /* mail_id = DEC_MAILID_PAUSE_ON : No parameter */ 00050 00051 /* mail_id = DEC_MAILID_PAUSE_OFF : No parameter */ 00052 00053 /* mail_id = DEC_MAILID_STOP : No parameter */ 00054 00055 /* mail_id = DEC_MAILID_CLOSE */ 00056 #define MAIL_CLOSE_CB (MAIL_PARAM0) /* Callback function */ 00057 00058 /* mail_id = DEC_MAILID_CB_AUD_DATA_OUT */ 00059 #define MAIL_DATA_OUT_RESULT (MAIL_PARAM0) /* Result of the process */ 00060 00061 /* mail_id = DEC_MAILID_SCUX_WRITE_FIN */ 00062 #define MAIL_SCUX_WRITE_RESULT (MAIL_PARAM0) /* Result of the process */ 00063 #define MAIL_SCUX_WRITE_BUF_INDEX (MAIL_PARAM1) /* Index number of PCM buffer */ 00064 00065 /* mail_id = DEC_MAILID_SCUX_FLUSH_FIN */ 00066 #define MAIL_SCUX_FLUSH_RESULT (MAIL_PARAM0) /* Result of the process */ 00067 00068 00069 /*--- Macro definition of PCM buffer ---*/ 00070 #define UNIT_TIME_MS (50u) /* Unit time of PCM data processing (ms) */ 00071 #define SEC_TO_MSEC (1000u) 00072 00073 /* Sample number per uint time (ms) */ 00074 #define SAMPLE_NUM_PER_UNIT_MS (((UNIT_TIME_MS * DEC_INPUT_MAX_SAMPLE_RATE) / SEC_TO_MSEC) * DEC_OUTPUT_CHANNEL_NUM) 00075 /* Max number of samples per 1 block */ 00076 #define MAX_SAMPLE_PER_1BLOCK (DEC_MAX_BLOCK_SIZE * DEC_OUTPUT_CHANNEL_NUM) 00077 00078 #define PCM_BUF_NUM (2u) 00079 #define TOTAL_SAMPLE_NUM (MAX_SAMPLE_PER_1BLOCK + SAMPLE_NUM_PER_UNIT_MS) 00080 00081 #define PCM_BUF_SINGLE (1) 00082 #define PCM_BUF_TOP_ID (0) 00083 00084 /*--- Macro definition of R_BSP_Scux ---*/ 00085 #define SCUX_INT_LEVEL (0x80) 00086 #define SCUX_READ_NUM (DEC_SCUX_READ_NUM) 00087 #define SCUX_WRITE_NUM (PCM_BUF_NUM) 00088 00089 /* 4 bytes aligned. No cache memory. */ 00090 #define NC_BSS_SECT __attribute__((section("NC_BSS"),aligned(4))) 00091 00092 /*--- User defined types of mbed-rtos mail ---*/ 00093 typedef enum { 00094 DEC_MAILID_DUMMY = 0, 00095 DEC_MAILID_OPEN, /* Requests the opening of the decoder. */ 00096 DEC_MAILID_PLAY, /* Requests the starting of the playback. */ 00097 DEC_MAILID_PAUSE_ON, /* Requests the starting of the pause. */ 00098 DEC_MAILID_PAUSE_OFF, /* Requests the stopping of the pause. */ 00099 DEC_MAILID_STOP, /* Requests the stopping of the playback. */ 00100 DEC_MAILID_CLOSE, /* Requests the closing of the decoder. */ 00101 DEC_MAILID_CB_AUD_DATA_OUT, /* Finished the preparation for the audio output. */ 00102 DEC_MAILID_SCUX_WRITE_FIN, /* Finished the writing process of SCUX. */ 00103 DEC_MAILID_SCUX_FLUSH_FIN, /* Finished the flush process of SCUX. */ 00104 DEC_MAILID_NUM 00105 } DEC_MAIL_ID; 00106 00107 typedef struct { 00108 DEC_MAIL_ID mail_id; 00109 uint32_t param[MAIL_PARAM_NUM]; 00110 } dec_mail_t; 00111 00112 /*--- User defined types of decode thread ---*/ 00113 /* The playback information of the playback file */ 00114 typedef struct { 00115 SYS_PlayStat play_stat; /* Playback status */ 00116 uint32_t play_time; /* Playback start time */ 00117 uint32_t total_time; /* Total playback time */ 00118 } play_info_t; 00119 00120 /* Control data of Decode thread */ 00121 typedef struct { 00122 play_info_t play_info; 00123 flac_ctrl_t flac_ctrl; 00124 } dec_ctrl_t; 00125 00126 /* Status of Decode thread */ 00127 typedef enum { 00128 DEC_ST_IDLE = 0, /* Idle */ 00129 DEC_ST_META_FIN, /* Finished the decoding until a metadata */ 00130 DEC_ST_PLAY, /* Decoder start */ 00131 DEC_ST_PAUSE, /* Decoder pause */ 00132 DEC_ST_STOP_PREPARE, /* Preparing of decoder stop */ 00133 DEC_ST_STOP, /* Decoder stop */ 00134 DEC_ST_NUM 00135 } DEC_STATE; 00136 00137 static Mail<dec_mail_t, MAIL_QUEUE_SIZE> mail_box; 00138 static R_BSP_Scux scux(SCUX_CH_0, SCUX_INT_LEVEL, SCUX_WRITE_NUM, SCUX_READ_NUM); 00139 00140 static bool open_proc(flac_ctrl_t * const p_ctrl, 00141 FILE * const p_handle, const DEC_CbOpen p_cb); 00142 static void close_proc(flac_ctrl_t * const p_ctrl, const DEC_CbClose p_cb); 00143 static bool play_proc(flac_ctrl_t * const p_ctrl, const uint32_t buf_id, 00144 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num); 00145 static bool pause_proc(const uint32_t buf_id, 00146 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num); 00147 static uint32_t get_audio_data(flac_ctrl_t * const p_ctrl, 00148 int32_t * const p_buf, const uint32_t buf_num); 00149 static void data_out_callback(const bool result); 00150 static void write_callback(void * p_data, int32_t result, void * p_app_data); 00151 static void flush_callback(int32_t result); 00152 static bool send_mail(const DEC_MAIL_ID mail_id, 00153 const uint32_t param0, const uint32_t param1); 00154 static bool recv_mail(DEC_MAIL_ID * const p_mail_id, 00155 uint32_t * const p_param0, uint32_t * const p_param1); 00156 static void update_decode_stat(const SYS_PlayStat stat, play_info_t * const p_play_info); 00157 static void update_decode_playtime(const uint32_t play_time, play_info_t * const p_play_info); 00158 static void init_decode_playinfo(const uint32_t total_time, play_info_t * const p_play_info); 00159 static void notify_decode_stat(const play_info_t * const p_play_info); 00160 00161 void dec_thread(void const *argument) 00162 { 00163 dec_ctrl_t dec_ctrl; /* Control data of Decode thread */ 00164 DEC_STATE dec_stat; /* Status of Decode thread */ 00165 DEC_MAIL_ID mail_type; 00166 uint32_t mail_param[MAIL_PARAM_NUM]; 00167 uint32_t buf_id; 00168 uint32_t buf_num; 00169 uint32_t time_code; 00170 bool result; 00171 static int32_t NC_BSS_SECT pcm_buf[PCM_BUF_NUM][TOTAL_SAMPLE_NUM]; 00172 00173 UNUSED_ARG(argument); 00174 dec_stat = DEC_ST_IDLE; 00175 while (1) { 00176 result = recv_mail(&mail_type, &mail_param[MAIL_PARAM0], &mail_param[MAIL_PARAM1]); 00177 if (result == true) { 00178 /* State transition processing */ 00179 switch (dec_stat) { 00180 case DEC_ST_META_FIN: /* Finished the decoding until a metadata */ 00181 if (mail_type == DEC_MAILID_PLAY) { 00182 time_code = flac_get_total_time(&dec_ctrl.flac_ctrl); 00183 init_decode_playinfo(time_code, &dec_ctrl.play_info); 00184 update_decode_stat(SYS_PLAYSTAT_PLAY, &dec_ctrl.play_info); 00185 (void) aud_req_data_out(&data_out_callback); 00186 dec_stat = DEC_ST_PLAY; 00187 } else if (mail_type == DEC_MAILID_CLOSE) { 00188 scux.ClearStop(); 00189 close_proc(&dec_ctrl.flac_ctrl, (DEC_CbClose)mail_param[MAIL_CLOSE_CB]); 00190 dec_stat = DEC_ST_IDLE; 00191 } else { 00192 /* DO NOTHING */ 00193 } 00194 break; 00195 case DEC_ST_PLAY: /* Decoder start */ 00196 if (mail_type == DEC_MAILID_PAUSE_ON) { 00197 update_decode_stat(SYS_PLAYSTAT_PAUSE, &dec_ctrl.play_info); 00198 dec_stat = DEC_ST_PAUSE; 00199 } else if (mail_type == DEC_MAILID_STOP) { 00200 scux.ClearStop(); 00201 (void) aud_req_zero_out(); 00202 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00203 dec_stat = DEC_ST_STOP; 00204 } else if ((mail_type == DEC_MAILID_CB_AUD_DATA_OUT) || 00205 (mail_type == DEC_MAILID_SCUX_WRITE_FIN)) { 00206 if (mail_type == DEC_MAILID_SCUX_WRITE_FIN) { 00207 buf_id = mail_param[MAIL_SCUX_WRITE_BUF_INDEX]; 00208 buf_num = PCM_BUF_SINGLE; 00209 } else { 00210 buf_id = PCM_BUF_TOP_ID; 00211 buf_num = PCM_BUF_NUM; 00212 } 00213 result = play_proc(&dec_ctrl.flac_ctrl, buf_id, &pcm_buf[buf_id], buf_num); 00214 if (result == true) { 00215 time_code = flac_get_play_time(&dec_ctrl.flac_ctrl); 00216 update_decode_playtime(time_code, &dec_ctrl.play_info); 00217 /* "dec_stat" variable does not change. */ 00218 } else { 00219 result = scux.FlushStop(&flush_callback); 00220 if (result == true) { 00221 dec_stat = DEC_ST_STOP_PREPARE; 00222 } else { 00223 /* Error occurred by SCUX driver. */ 00224 (void) aud_req_zero_out(); 00225 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00226 dec_stat = DEC_ST_STOP; 00227 } 00228 } 00229 } else { 00230 /* DO NOTHING */ 00231 } 00232 break; 00233 case DEC_ST_PAUSE: /* Decoder pause */ 00234 if (mail_type == DEC_MAILID_PAUSE_OFF) { 00235 update_decode_stat(SYS_PLAYSTAT_PLAY, &dec_ctrl.play_info); 00236 dec_stat = DEC_ST_PLAY; 00237 } else if (mail_type == DEC_MAILID_STOP) { 00238 scux.ClearStop(); 00239 (void) aud_req_zero_out(); 00240 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00241 dec_stat = DEC_ST_STOP; 00242 } else if ((mail_type == DEC_MAILID_CB_AUD_DATA_OUT) || 00243 (mail_type == DEC_MAILID_SCUX_WRITE_FIN)) { 00244 if (mail_type == DEC_MAILID_SCUX_WRITE_FIN) { 00245 buf_id = mail_param[MAIL_SCUX_WRITE_BUF_INDEX]; 00246 buf_num = PCM_BUF_SINGLE; 00247 } else { 00248 buf_id = PCM_BUF_TOP_ID; 00249 buf_num = PCM_BUF_NUM; 00250 } 00251 result = pause_proc(buf_id, &pcm_buf[buf_id], buf_num); 00252 if (result == true) { 00253 /* "dec_stat" variable does not change. */ 00254 } else { 00255 result = scux.FlushStop(&flush_callback); 00256 if (result == true) { 00257 dec_stat = DEC_ST_STOP_PREPARE; 00258 } else { 00259 /* Error occurred by SCUX driver. */ 00260 (void) aud_req_zero_out(); 00261 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00262 dec_stat = DEC_ST_STOP; 00263 } 00264 } 00265 } else { 00266 /* DO NOTHING */ 00267 } 00268 break; 00269 case DEC_ST_STOP_PREPARE: /* Preparing of decoder stop */ 00270 if (mail_type == DEC_MAILID_SCUX_FLUSH_FIN) { 00271 (void) aud_req_zero_out(); 00272 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00273 dec_stat = DEC_ST_STOP; 00274 } else { 00275 /* DO NOTHING */ 00276 } 00277 break; 00278 case DEC_ST_STOP: /* Decoder stop */ 00279 if (mail_type == DEC_MAILID_CLOSE) { 00280 close_proc(&dec_ctrl.flac_ctrl, (DEC_CbClose)mail_param[MAIL_CLOSE_CB]); 00281 dec_stat = DEC_ST_IDLE; 00282 } else { 00283 /* DO NOTHING */ 00284 } 00285 break; 00286 case DEC_ST_IDLE: /* Idle */ 00287 default: 00288 if (mail_type == DEC_MAILID_OPEN) { 00289 result = open_proc(&dec_ctrl.flac_ctrl, 00290 (FILE*)mail_param[MAIL_OPEN_FILE], 00291 (DEC_CbOpen)mail_param[MAIL_OPEN_CB]); 00292 if (result == true) { 00293 dec_stat = DEC_ST_META_FIN; 00294 } else { 00295 /* "dec_stat" variable does not change. */ 00296 } 00297 } else { 00298 dec_stat = DEC_ST_IDLE; /* This is fail-safe processing. */ 00299 } 00300 break; 00301 } 00302 } 00303 } 00304 } 00305 00306 bool dec_open(FILE * const p_handle, const DEC_CbOpen p_cb) 00307 { 00308 bool ret = false; 00309 00310 if ((p_handle != NULL) && (p_cb != NULL)) { 00311 ret = send_mail(DEC_MAILID_OPEN, (uint32_t)p_cb, (uint32_t)p_handle); 00312 } 00313 return ret; 00314 } 00315 00316 bool dec_play(void) 00317 { 00318 bool ret = false; 00319 00320 ret = send_mail(DEC_MAILID_PLAY, MAIL_PARAM_NON, MAIL_PARAM_NON); 00321 00322 return ret; 00323 } 00324 00325 bool dec_pause_on(void) 00326 { 00327 bool ret = false; 00328 00329 ret = send_mail(DEC_MAILID_PAUSE_ON, MAIL_PARAM_NON, MAIL_PARAM_NON); 00330 00331 return ret; 00332 } 00333 00334 bool dec_pause_off(void) 00335 { 00336 bool ret = false; 00337 00338 ret = send_mail(DEC_MAILID_PAUSE_OFF, MAIL_PARAM_NON, MAIL_PARAM_NON); 00339 00340 return ret; 00341 } 00342 00343 bool dec_stop(void) 00344 { 00345 bool ret; 00346 00347 ret = send_mail(DEC_MAILID_STOP, MAIL_PARAM_NON, MAIL_PARAM_NON); 00348 00349 return ret; 00350 } 00351 00352 bool dec_close(const DEC_CbClose p_cb) 00353 { 00354 bool ret = false; 00355 00356 if (p_cb != NULL) { 00357 ret = send_mail(DEC_MAILID_CLOSE, (uint32_t)p_cb, MAIL_PARAM_NON); 00358 } 00359 return ret; 00360 } 00361 00362 bool dec_scux_read(void * const p_data, const uint32_t data_size, 00363 const rbsp_data_conf_t * const p_data_conf) 00364 { 00365 bool ret = false; 00366 int32_t result; 00367 00368 result = scux.read(p_data, data_size, p_data_conf); 00369 if (result == ESUCCESS) { 00370 ret = true; 00371 } 00372 return ret; 00373 } 00374 00375 /** Executes the opening process of the decoder 00376 * 00377 * @param p_ctrl Pointer to the control data of FLAC module. 00378 * @param p_handle Pointer to the handle of FLAC file. 00379 * @param p_cb Pointer to the callback for notification of the process result. 00380 * 00381 * @returns 00382 * Results of process. true is success. false is failure. 00383 */ 00384 static bool open_proc(flac_ctrl_t * const p_ctrl, FILE * const p_handle, const DEC_CbOpen p_cb) 00385 { 00386 bool ret = false; 00387 bool result; 00388 scux_src_usr_cfg_t conf; 00389 00390 if ((p_ctrl != NULL) && (p_handle != NULL) && (p_cb != NULL)) { 00391 result = flac_open(p_handle, p_ctrl); 00392 if (result == true) { 00393 /* Sets SCUX config */ 00394 conf.src_enable = true; 00395 conf.word_len = SCUX_DATA_LEN_24; 00396 conf.mode_sync = true; 00397 conf.input_rate = p_ctrl->sample_rate; 00398 conf.output_rate = DEC_OUTPUT_SAMPLE_RATE; 00399 conf.select_in_data_ch[0] = SELECT_IN_DATA_CH_0; 00400 conf.select_in_data_ch[1] = SELECT_IN_DATA_CH_1; 00401 result = scux.SetSrcCfg(&conf); 00402 if (result == true) { 00403 ret = scux.TransStart(); 00404 } 00405 } 00406 p_cb(ret, p_ctrl->sample_rate, p_ctrl->channel_num); 00407 } 00408 return ret; 00409 } 00410 00411 /** Executes the closing process of the decoder 00412 * 00413 * @param p_ctrl Pointer to the control data of FLAC module. 00414 * @param p_cb Pointer to the callback for notification of the process result. 00415 * 00416 * @returns 00417 * Results of process. true is success. false is failure. 00418 */ 00419 static void close_proc(flac_ctrl_t * const p_ctrl, const DEC_CbClose p_cb) 00420 { 00421 if ((p_ctrl != NULL) && (p_cb != NULL)) { 00422 flac_close(p_ctrl); 00423 p_cb(); 00424 } 00425 } 00426 00427 /** Executes the starting process of the pause 00428 * 00429 * @param p_ctrl Pointer to the control data of FLAC module. 00430 * @param buf_id Index of PCM buffer array. 00431 * @param p_buf Pointer to PCM buffer array to use in this process. 00432 * @param element_num Elements number of PCM buffer array. 00433 * 00434 * @returns 00435 * Results of process. true is success. false is failure. 00436 */ 00437 static bool pause_proc(const uint32_t buf_id, 00438 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num) 00439 { 00440 bool ret = false; 00441 uint32_t i; 00442 int32_t result; 00443 const uint32_t pause_data_size = SAMPLE_NUM_PER_UNIT_MS * sizeof(*p_buf[0]); 00444 rbsp_data_conf_t cb_conf = { 00445 &write_callback, 00446 NULL 00447 }; 00448 00449 if ((p_buf != NULL) && (element_num > 0u) && 00450 (element_num <= PCM_BUF_NUM) && ((buf_id + element_num) <= PCM_BUF_NUM)) { 00451 /* Audio output process */ 00452 result = ESUCCESS; 00453 for (i = 0; (i < element_num) && (result == ESUCCESS); i++) { 00454 (void) memset(&p_buf[i], 0, pause_data_size); 00455 cb_conf.p_app_data = (void *)(buf_id + i); 00456 result = scux.write(&p_buf[i], pause_data_size, &cb_conf); 00457 } 00458 if (result == ESUCCESS) { 00459 ret = true; 00460 } 00461 } 00462 return ret; 00463 } 00464 00465 /** Executes the starting process of the playback 00466 * 00467 * @param p_ctrl Pointer to the control data of FLAC module. 00468 * @param buf_id Index of PCM buffer array. 00469 * @param p_buf Pointer to PCM buffer array to use in this process. 00470 * @param element_num Elements number of PCM buffer array. 00471 * 00472 * @returns 00473 * Results of process. true is success. false is failure. 00474 */ 00475 static bool play_proc(flac_ctrl_t * const p_ctrl, const uint32_t buf_id, 00476 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num) 00477 { 00478 bool ret = false; 00479 int32_t result; 00480 uint32_t i; 00481 uint32_t decoded_cnt; 00482 uint32_t num; 00483 uint32_t read_byte[PCM_BUF_NUM]; 00484 rbsp_data_conf_t cb_conf = { 00485 &write_callback, 00486 NULL 00487 }; 00488 00489 if ((p_ctrl != NULL) && (p_buf != NULL) && (element_num > 0u) && 00490 (element_num <= PCM_BUF_NUM) && ((buf_id + element_num) <= PCM_BUF_NUM)) { 00491 /* FLAC decoder process */ 00492 decoded_cnt = 0u; 00493 do { 00494 num = get_audio_data(p_ctrl, p_buf[decoded_cnt], sizeof(p_buf[0])/sizeof(*p_buf[0])); 00495 read_byte[decoded_cnt] = num * sizeof(num); 00496 if (num > 0u) { 00497 decoded_cnt++; 00498 } 00499 } while ((decoded_cnt < element_num) && (num > 0u)); 00500 /* Audio output process */ 00501 if (decoded_cnt > 0u) { 00502 result = ESUCCESS; 00503 for (i = 0; (i < decoded_cnt) && (result == ESUCCESS); i++) { 00504 cb_conf.p_app_data = (void *)(buf_id + i); 00505 result = scux.write(&p_buf[i], read_byte[i], &cb_conf); 00506 } 00507 if (result == ESUCCESS) { 00508 ret = true; 00509 } 00510 } 00511 } 00512 return ret; 00513 } 00514 00515 /** Gets the decoded data from FLAC decoder library 00516 * 00517 * @param p_ctrl Pointer to the control data of FLAC module. 00518 * @param p_buf Pointer to PCM buffer array to store the decoded data. 00519 * @param buf_num Elements number of PCM buffer array. 00520 * 00521 * @returns 00522 * Elements number of decoded data. 00523 */ 00524 static uint32_t get_audio_data(flac_ctrl_t * const p_ctrl, 00525 int32_t * const p_buf, const uint32_t buf_num) 00526 { 00527 uint32_t read_cnt = 0u; 00528 bool result; 00529 00530 if ((p_ctrl != NULL) && (p_buf != NULL) && (buf_num > 0u)) { 00531 result = flac_set_pcm_buf(p_ctrl, p_buf, buf_num); 00532 while ((result == true) && ((read_cnt + MAX_SAMPLE_PER_1BLOCK) <= buf_num)) { 00533 result = flac_decode(p_ctrl); 00534 read_cnt = flac_get_pcm_cnt(p_ctrl); 00535 } 00536 } 00537 return read_cnt; 00538 } 00539 00540 /** Callback function of Audio Out Thread 00541 * 00542 * @param result Result of the process of Audio Out Thread 00543 */ 00544 static void data_out_callback(const bool result) 00545 { 00546 (void) send_mail(DEC_MAILID_CB_AUD_DATA_OUT, (uint32_t)result, MAIL_PARAM_NON); 00547 } 00548 00549 /** Callback function of SCUX driver 00550 * 00551 * @param p_data Pointer to PCM byffer array. 00552 * @param result Result of the process. 00553 * @param p_app_data The control ID of PCM buffer. 00554 */ 00555 static void write_callback(void * p_data, int32_t result, void * p_app_data) 00556 { 00557 const uint32_t buf_id = (uint32_t)p_app_data; 00558 bool flag_result; 00559 00560 UNUSED_ARG(p_data); 00561 if (result > 0) { 00562 flag_result = true; 00563 } else { 00564 flag_result = false; 00565 } 00566 (void) send_mail(DEC_MAILID_SCUX_WRITE_FIN, (uint32_t)flag_result, buf_id); 00567 } 00568 00569 /** Callback function of SCUX driver 00570 * 00571 * @param result Result of the process. 00572 */ 00573 static void flush_callback(int32_t result) 00574 { 00575 bool flag_result; 00576 00577 if (result > 0) { 00578 flag_result = true; 00579 } else { 00580 flag_result = false; 00581 } 00582 (void) send_mail(DEC_MAILID_SCUX_FLUSH_FIN, (uint32_t)flag_result, MAIL_PARAM_NON); 00583 } 00584 00585 /** Sends the mail to Decode thread 00586 * 00587 * @param mail_id Mail ID 00588 * @param param0 Parameter 0 of this mail 00589 * @param param1 Parameter 1 of this mail 00590 * 00591 * @returns 00592 * Results of process. true is success. false is failure. 00593 */ 00594 static bool send_mail(const DEC_MAIL_ID mail_id, 00595 const uint32_t param0, const uint32_t param1) 00596 { 00597 bool ret = false; 00598 osStatus stat; 00599 dec_mail_t * const p_mail = mail_box.alloc(); 00600 00601 if (p_mail != NULL) { 00602 p_mail->mail_id = mail_id; 00603 p_mail->param[MAIL_PARAM0] = param0; 00604 p_mail->param[MAIL_PARAM1] = param1; 00605 stat = mail_box.put(p_mail); 00606 if (stat == osOK) { 00607 ret = true; 00608 } else { 00609 (void) mail_box.free(p_mail); 00610 } 00611 } 00612 return ret; 00613 } 00614 00615 /** Receives the mail to Decode thread 00616 * 00617 * @param p_mail_id Pointer to the variable to store the mail ID 00618 * @param p_param0 Pointer to the variable to store the parameter 0 of this mail 00619 * @param p_param1 Pointer to the variable to store the parameter 1 of this mail 00620 * 00621 * @returns 00622 * Results of process. true is success. false is failure. 00623 */ 00624 static bool recv_mail(DEC_MAIL_ID * const p_mail_id, 00625 uint32_t * const p_param0, uint32_t * const p_param1) 00626 { 00627 bool ret = false; 00628 osEvent evt; 00629 dec_mail_t *p_mail; 00630 00631 if ((p_mail_id != NULL) && (p_param0 != NULL) && (p_param1 != NULL)) { 00632 evt = mail_box.get(); 00633 if (evt.status == osEventMail) { 00634 p_mail = (dec_mail_t *)evt.value.p; 00635 if (p_mail != NULL) { 00636 *p_mail_id = p_mail->mail_id; 00637 *p_param0 = p_mail->param[MAIL_PARAM0]; 00638 *p_param1 = p_mail->param[MAIL_PARAM1]; 00639 ret = true; 00640 } 00641 (void) mail_box.free(p_mail); 00642 } 00643 } 00644 return ret; 00645 } 00646 00647 /** Updates the status of Decode thread 00648 * 00649 * @param stat New status of Decode thread 00650 * @param p_play_info Pointer to the playback information of the playback file 00651 */ 00652 static void update_decode_stat(const SYS_PlayStat stat, play_info_t * const p_play_info) 00653 { 00654 if (p_play_info != NULL) { 00655 if (p_play_info->play_stat != stat) { 00656 p_play_info->play_stat = stat; 00657 notify_decode_stat(p_play_info); 00658 } 00659 } 00660 } 00661 00662 /** Updates the playback time 00663 * 00664 * @param play_time Current playback time 00665 * @param p_play_info Pointer to the playback information of the playback file 00666 */ 00667 static void update_decode_playtime(const uint32_t play_time, play_info_t * const p_play_info) 00668 { 00669 if (p_play_info != NULL) { 00670 if (p_play_info->play_time != play_time) { 00671 p_play_info->play_time = play_time; 00672 notify_decode_stat(p_play_info); 00673 } 00674 } 00675 } 00676 00677 /** Initialises the playback information 00678 * 00679 * @param total_time Total playback time 00680 * @param p_play_info Pointer to the playback information of the playback file 00681 */ 00682 static void init_decode_playinfo(const uint32_t total_time, play_info_t * const p_play_info) 00683 { 00684 if (p_play_info != NULL) { 00685 p_play_info->play_stat = SYS_PLAYSTAT_STOP; 00686 p_play_info->play_time = 0u; 00687 p_play_info->total_time = total_time; 00688 } 00689 } 00690 00691 /** Notifies Main thread of the status of Decode thread 00692 * 00693 * @param p_play_info Pointer to the playback information of the playback file 00694 */ 00695 static void notify_decode_stat(const play_info_t * const p_play_info) 00696 { 00697 if (p_play_info != NULL) { 00698 (void) sys_notify_play_time(p_play_info->play_stat, 00699 p_play_info->play_time, p_play_info->total_time); 00700 } 00701 }
Generated on Tue Jul 12 2022 19:32:28 by 1.7.2