Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: R_BSP TLV320_RBSP USBHost_custom
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 (3u) 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 #if defined(__ICCARM__) 00091 #define NC_BSS_SECT @ ".mirrorram" 00092 #else 00093 #define NC_BSS_SECT __attribute__((section("NC_BSS"),aligned(4))) 00094 #endif 00095 00096 /*--- User defined types of mbed-rtos mail ---*/ 00097 typedef enum { 00098 DEC_MAILID_DUMMY = 0, 00099 DEC_MAILID_OPEN, /* Requests the opening of the decoder. */ 00100 DEC_MAILID_PLAY, /* Requests the starting of the playback. */ 00101 DEC_MAILID_PAUSE_ON, /* Requests the starting of the pause. */ 00102 DEC_MAILID_PAUSE_OFF, /* Requests the stopping of the pause. */ 00103 DEC_MAILID_STOP, /* Requests the stopping of the playback. */ 00104 DEC_MAILID_CLOSE, /* Requests the closing of the decoder. */ 00105 DEC_MAILID_CB_AUD_DATA_OUT, /* Finished the preparation for the audio output. */ 00106 DEC_MAILID_SCUX_WRITE_FIN, /* Finished the writing process of SCUX. */ 00107 DEC_MAILID_SCUX_FLUSH_FIN, /* Finished the flush process of SCUX. */ 00108 DEC_MAILID_NUM 00109 } DEC_MAIL_ID; 00110 00111 typedef struct { 00112 DEC_MAIL_ID mail_id; 00113 uint32_t param[MAIL_PARAM_NUM]; 00114 } dec_mail_t; 00115 00116 /*--- User defined types of decode thread ---*/ 00117 /* The playback information of the playback file */ 00118 typedef struct { 00119 SYS_PlayStat play_stat; /* Playback status */ 00120 uint32_t play_time; /* Playback start time */ 00121 uint32_t total_time; /* Total playback time */ 00122 } play_info_t; 00123 00124 /* Control data of Decode thread */ 00125 typedef struct { 00126 play_info_t play_info; 00127 flac_ctrl_t flac_ctrl; 00128 } dec_ctrl_t; 00129 00130 /* Status of Decode thread */ 00131 typedef enum { 00132 DEC_ST_IDLE = 0, /* Idle */ 00133 DEC_ST_META_FIN, /* Finished the decoding until a metadata */ 00134 DEC_ST_PLAY, /* Decoder start */ 00135 DEC_ST_PAUSE, /* Decoder pause */ 00136 DEC_ST_STOP_PREPARE, /* Preparing of decoder stop */ 00137 DEC_ST_STOP, /* Decoder stop */ 00138 DEC_ST_NUM 00139 } DEC_STATE; 00140 00141 static Mail<dec_mail_t, MAIL_QUEUE_SIZE> mail_box; 00142 static R_BSP_Scux scux(SCUX_CH_0, SCUX_INT_LEVEL, SCUX_WRITE_NUM, SCUX_READ_NUM); 00143 00144 static bool open_proc(flac_ctrl_t * const p_ctrl, 00145 FILE * const p_handle, const DEC_CbOpen p_cb); 00146 static void close_proc(flac_ctrl_t * const p_ctrl, const DEC_CbClose p_cb); 00147 static bool play_proc(flac_ctrl_t * const p_ctrl, const uint32_t buf_id, 00148 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num); 00149 static bool pause_proc(const uint32_t buf_id, 00150 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num); 00151 static uint32_t get_audio_data(flac_ctrl_t * const p_ctrl, 00152 int32_t * const p_buf, const uint32_t buf_num); 00153 static void data_out_callback(const bool result); 00154 static void write_callback(void * p_data, int32_t result, void * p_app_data); 00155 static void flush_callback(int32_t result); 00156 static bool send_mail(const DEC_MAIL_ID mail_id, 00157 const uint32_t param0, const uint32_t param1); 00158 static bool recv_mail(DEC_MAIL_ID * const p_mail_id, 00159 uint32_t * const p_param0, uint32_t * const p_param1); 00160 static void update_decode_stat(const SYS_PlayStat stat, play_info_t * const p_play_info); 00161 static void update_decode_playtime(const uint32_t play_time, play_info_t * const p_play_info); 00162 static void init_decode_playinfo(const uint32_t total_time, play_info_t * const p_play_info); 00163 static void notify_decode_stat(const play_info_t * const p_play_info); 00164 00165 void dec_thread(void const *argument) 00166 { 00167 dec_ctrl_t dec_ctrl; /* Control data of Decode thread */ 00168 DEC_STATE dec_stat; /* Status of Decode thread */ 00169 DEC_MAIL_ID mail_type; 00170 uint32_t mail_param[MAIL_PARAM_NUM]; 00171 uint32_t buf_id; 00172 uint32_t buf_num; 00173 uint32_t time_code; 00174 bool result; 00175 #if defined(__ICCARM__) 00176 static int32_t pcm_buf[PCM_BUF_NUM][TOTAL_SAMPLE_NUM] NC_BSS_SECT; 00177 #else 00178 static int32_t NC_BSS_SECT pcm_buf[PCM_BUF_NUM][TOTAL_SAMPLE_NUM]; 00179 #endif 00180 00181 UNUSED_ARG(argument); 00182 dec_stat = DEC_ST_IDLE; 00183 while (1) { 00184 result = recv_mail(&mail_type, &mail_param[MAIL_PARAM0], &mail_param[MAIL_PARAM1]); 00185 if (result == true) { 00186 /* State transition processing */ 00187 switch (dec_stat) { 00188 case DEC_ST_META_FIN: /* Finished the decoding until a metadata */ 00189 if (mail_type == DEC_MAILID_PLAY) { 00190 time_code = flac_get_total_time(&dec_ctrl.flac_ctrl); 00191 init_decode_playinfo(time_code, &dec_ctrl.play_info); 00192 update_decode_stat(SYS_PLAYSTAT_PLAY, &dec_ctrl.play_info); 00193 (void) aud_req_data_out(&data_out_callback); 00194 dec_stat = DEC_ST_PLAY; 00195 } else if (mail_type == DEC_MAILID_CLOSE) { 00196 scux.ClearStop(); 00197 close_proc(&dec_ctrl.flac_ctrl, (DEC_CbClose)mail_param[MAIL_CLOSE_CB]); 00198 dec_stat = DEC_ST_IDLE; 00199 } else { 00200 /* DO NOTHING */ 00201 } 00202 break; 00203 case DEC_ST_PLAY: /* Decoder start */ 00204 if (mail_type == DEC_MAILID_PAUSE_ON) { 00205 update_decode_stat(SYS_PLAYSTAT_PAUSE, &dec_ctrl.play_info); 00206 dec_stat = DEC_ST_PAUSE; 00207 } else if (mail_type == DEC_MAILID_STOP) { 00208 scux.ClearStop(); 00209 (void) aud_req_zero_out(); 00210 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00211 dec_stat = DEC_ST_STOP; 00212 } else if ((mail_type == DEC_MAILID_CB_AUD_DATA_OUT) || 00213 (mail_type == DEC_MAILID_SCUX_WRITE_FIN)) { 00214 if (mail_type == DEC_MAILID_SCUX_WRITE_FIN) { 00215 buf_id = mail_param[MAIL_SCUX_WRITE_BUF_INDEX]; 00216 buf_num = PCM_BUF_SINGLE; 00217 } else { 00218 buf_id = PCM_BUF_TOP_ID; 00219 buf_num = PCM_BUF_NUM; 00220 } 00221 result = play_proc(&dec_ctrl.flac_ctrl, buf_id, &pcm_buf[buf_id], buf_num); 00222 if (result == true) { 00223 time_code = flac_get_play_time(&dec_ctrl.flac_ctrl); 00224 update_decode_playtime(time_code, &dec_ctrl.play_info); 00225 /* "dec_stat" variable does not change. */ 00226 } else { 00227 result = scux.FlushStop(&flush_callback); 00228 if (result == true) { 00229 dec_stat = DEC_ST_STOP_PREPARE; 00230 } else { 00231 /* Error occurred by SCUX driver. */ 00232 (void) aud_req_zero_out(); 00233 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00234 dec_stat = DEC_ST_STOP; 00235 } 00236 } 00237 } else { 00238 /* DO NOTHING */ 00239 } 00240 break; 00241 case DEC_ST_PAUSE: /* Decoder pause */ 00242 if (mail_type == DEC_MAILID_PAUSE_OFF) { 00243 update_decode_stat(SYS_PLAYSTAT_PLAY, &dec_ctrl.play_info); 00244 dec_stat = DEC_ST_PLAY; 00245 } else if (mail_type == DEC_MAILID_STOP) { 00246 scux.ClearStop(); 00247 (void) aud_req_zero_out(); 00248 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00249 dec_stat = DEC_ST_STOP; 00250 } else if ((mail_type == DEC_MAILID_CB_AUD_DATA_OUT) || 00251 (mail_type == DEC_MAILID_SCUX_WRITE_FIN)) { 00252 if (mail_type == DEC_MAILID_SCUX_WRITE_FIN) { 00253 buf_id = mail_param[MAIL_SCUX_WRITE_BUF_INDEX]; 00254 buf_num = PCM_BUF_SINGLE; 00255 } else { 00256 buf_id = PCM_BUF_TOP_ID; 00257 buf_num = PCM_BUF_NUM; 00258 } 00259 result = pause_proc(buf_id, &pcm_buf[buf_id], buf_num); 00260 if (result == true) { 00261 /* "dec_stat" variable does not change. */ 00262 } else { 00263 result = scux.FlushStop(&flush_callback); 00264 if (result == true) { 00265 dec_stat = DEC_ST_STOP_PREPARE; 00266 } else { 00267 /* Error occurred by SCUX driver. */ 00268 (void) aud_req_zero_out(); 00269 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00270 dec_stat = DEC_ST_STOP; 00271 } 00272 } 00273 } else { 00274 /* DO NOTHING */ 00275 } 00276 break; 00277 case DEC_ST_STOP_PREPARE: /* Preparing of decoder stop */ 00278 if (mail_type == DEC_MAILID_SCUX_FLUSH_FIN) { 00279 (void) aud_req_zero_out(); 00280 update_decode_stat(SYS_PLAYSTAT_STOP, &dec_ctrl.play_info); 00281 dec_stat = DEC_ST_STOP; 00282 } else { 00283 /* DO NOTHING */ 00284 } 00285 break; 00286 case DEC_ST_STOP: /* Decoder stop */ 00287 if (mail_type == DEC_MAILID_CLOSE) { 00288 close_proc(&dec_ctrl.flac_ctrl, (DEC_CbClose)mail_param[MAIL_CLOSE_CB]); 00289 dec_stat = DEC_ST_IDLE; 00290 } else { 00291 /* DO NOTHING */ 00292 } 00293 break; 00294 case DEC_ST_IDLE: /* Idle */ 00295 default: 00296 if (mail_type == DEC_MAILID_OPEN) { 00297 result = open_proc(&dec_ctrl.flac_ctrl, 00298 (FILE*)mail_param[MAIL_OPEN_FILE], 00299 (DEC_CbOpen)mail_param[MAIL_OPEN_CB]); 00300 if (result == true) { 00301 dec_stat = DEC_ST_META_FIN; 00302 } else { 00303 /* "dec_stat" variable does not change. */ 00304 } 00305 } else { 00306 dec_stat = DEC_ST_IDLE; /* This is fail-safe processing. */ 00307 } 00308 break; 00309 } 00310 } 00311 } 00312 } 00313 00314 bool dec_open(FILE * const p_handle, const DEC_CbOpen p_cb) 00315 { 00316 bool ret = false; 00317 00318 if ((p_handle != NULL) && (p_cb != NULL)) { 00319 ret = send_mail(DEC_MAILID_OPEN, (uint32_t)p_cb, (uint32_t)p_handle); 00320 } 00321 return ret; 00322 } 00323 00324 bool dec_play(void) 00325 { 00326 bool ret = false; 00327 00328 ret = send_mail(DEC_MAILID_PLAY, MAIL_PARAM_NON, MAIL_PARAM_NON); 00329 00330 return ret; 00331 } 00332 00333 bool dec_pause_on(void) 00334 { 00335 bool ret = false; 00336 00337 ret = send_mail(DEC_MAILID_PAUSE_ON, MAIL_PARAM_NON, MAIL_PARAM_NON); 00338 00339 return ret; 00340 } 00341 00342 bool dec_pause_off(void) 00343 { 00344 bool ret = false; 00345 00346 ret = send_mail(DEC_MAILID_PAUSE_OFF, MAIL_PARAM_NON, MAIL_PARAM_NON); 00347 00348 return ret; 00349 } 00350 00351 bool dec_stop(void) 00352 { 00353 bool ret; 00354 00355 ret = send_mail(DEC_MAILID_STOP, MAIL_PARAM_NON, MAIL_PARAM_NON); 00356 00357 return ret; 00358 } 00359 00360 bool dec_close(const DEC_CbClose p_cb) 00361 { 00362 bool ret = false; 00363 00364 if (p_cb != NULL) { 00365 ret = send_mail(DEC_MAILID_CLOSE, (uint32_t)p_cb, MAIL_PARAM_NON); 00366 } 00367 return ret; 00368 } 00369 00370 bool dec_scux_read(void * const p_data, const uint32_t data_size, 00371 const rbsp_data_conf_t * const p_data_conf) 00372 { 00373 bool ret = false; 00374 int32_t result; 00375 00376 result = scux.read(p_data, data_size, p_data_conf); 00377 if (result == ESUCCESS) { 00378 ret = true; 00379 } 00380 return ret; 00381 } 00382 00383 /** Executes the opening process of the decoder 00384 * 00385 * @param p_ctrl Pointer to the control data of FLAC module. 00386 * @param p_handle Pointer to the handle of FLAC file. 00387 * @param p_cb Pointer to the callback for notification of the process result. 00388 * 00389 * @returns 00390 * Results of process. true is success. false is failure. 00391 */ 00392 static bool open_proc(flac_ctrl_t * const p_ctrl, FILE * const p_handle, const DEC_CbOpen p_cb) 00393 { 00394 bool ret = false; 00395 bool result; 00396 scux_src_usr_cfg_t conf; 00397 00398 if ((p_ctrl != NULL) && (p_handle != NULL) && (p_cb != NULL)) { 00399 result = flac_open(p_handle, p_ctrl); 00400 if (result == true) { 00401 /* Sets SCUX config */ 00402 conf.src_enable = true; 00403 conf.word_len = SCUX_DATA_LEN_24; 00404 conf.mode_sync = true; 00405 conf.input_rate = p_ctrl->sample_rate; 00406 conf.output_rate = DEC_OUTPUT_SAMPLE_RATE; 00407 conf.select_in_data_ch[0] = SELECT_IN_DATA_CH_0; 00408 conf.select_in_data_ch[1] = SELECT_IN_DATA_CH_1; 00409 result = scux.SetSrcCfg(&conf); 00410 if (result == true) { 00411 ret = scux.TransStart(); 00412 } 00413 } 00414 p_cb(ret, p_ctrl->sample_rate, p_ctrl->channel_num); 00415 } 00416 return ret; 00417 } 00418 00419 /** Executes the closing process of the decoder 00420 * 00421 * @param p_ctrl Pointer to the control data of FLAC module. 00422 * @param p_cb Pointer to the callback for notification of the process result. 00423 * 00424 * @returns 00425 * Results of process. true is success. false is failure. 00426 */ 00427 static void close_proc(flac_ctrl_t * const p_ctrl, const DEC_CbClose p_cb) 00428 { 00429 if ((p_ctrl != NULL) && (p_cb != NULL)) { 00430 flac_close(p_ctrl); 00431 p_cb(); 00432 } 00433 } 00434 00435 /** Executes the starting process of the pause 00436 * 00437 * @param p_ctrl Pointer to the control data of FLAC module. 00438 * @param buf_id Index of PCM buffer array. 00439 * @param p_buf Pointer to PCM buffer array to use in this process. 00440 * @param element_num Elements number of PCM buffer array. 00441 * 00442 * @returns 00443 * Results of process. true is success. false is failure. 00444 */ 00445 static bool pause_proc(const uint32_t buf_id, 00446 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num) 00447 { 00448 bool ret = false; 00449 uint32_t i; 00450 int32_t result; 00451 const uint32_t pause_data_size = SAMPLE_NUM_PER_UNIT_MS * sizeof(*p_buf[0]); 00452 rbsp_data_conf_t cb_conf = { 00453 &write_callback, 00454 NULL 00455 }; 00456 00457 if ((p_buf != NULL) && (element_num > 0u) && 00458 (element_num <= PCM_BUF_NUM) && ((buf_id + element_num) <= PCM_BUF_NUM)) { 00459 /* Audio output process */ 00460 result = ESUCCESS; 00461 for (i = 0; (i < element_num) && (result == ESUCCESS); i++) { 00462 (void) memset(&p_buf[i], 0, pause_data_size); 00463 cb_conf.p_app_data = (void *)(buf_id + i); 00464 result = scux.write(&p_buf[i], pause_data_size, &cb_conf); 00465 } 00466 if (result == ESUCCESS) { 00467 ret = true; 00468 } 00469 } 00470 return ret; 00471 } 00472 00473 /** Executes the starting process of the playback 00474 * 00475 * @param p_ctrl Pointer to the control data of FLAC module. 00476 * @param buf_id Index of PCM buffer array. 00477 * @param p_buf Pointer to PCM buffer array to use in this process. 00478 * @param element_num Elements number of PCM buffer array. 00479 * 00480 * @returns 00481 * Results of process. true is success. false is failure. 00482 */ 00483 static bool play_proc(flac_ctrl_t * const p_ctrl, const uint32_t buf_id, 00484 int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t element_num) 00485 { 00486 bool ret = false; 00487 int32_t result; 00488 uint32_t i; 00489 uint32_t decoded_cnt; 00490 uint32_t num; 00491 uint32_t read_byte[PCM_BUF_NUM]; 00492 rbsp_data_conf_t cb_conf = { 00493 &write_callback, 00494 NULL 00495 }; 00496 00497 if ((p_ctrl != NULL) && (p_buf != NULL) && (element_num > 0u) && 00498 (element_num <= PCM_BUF_NUM) && ((buf_id + element_num) <= PCM_BUF_NUM)) { 00499 /* FLAC decoder process */ 00500 decoded_cnt = 0u; 00501 do { 00502 num = get_audio_data(p_ctrl, p_buf[decoded_cnt], sizeof(p_buf[0])/sizeof(*p_buf[0])); 00503 read_byte[decoded_cnt] = num * sizeof(num); 00504 if (num > 0u) { 00505 decoded_cnt++; 00506 } 00507 } while ((decoded_cnt < element_num) && (num > 0u)); 00508 /* Audio output process */ 00509 if (decoded_cnt > 0u) { 00510 result = ESUCCESS; 00511 for (i = 0; (i < decoded_cnt) && (result == ESUCCESS); i++) { 00512 cb_conf.p_app_data = (void *)(buf_id + i); 00513 result = scux.write(&p_buf[i], read_byte[i], &cb_conf); 00514 } 00515 if (result == ESUCCESS) { 00516 ret = true; 00517 } 00518 } 00519 } 00520 return ret; 00521 } 00522 00523 /** Gets the decoded data from FLAC decoder library 00524 * 00525 * @param p_ctrl Pointer to the control data of FLAC module. 00526 * @param p_buf Pointer to PCM buffer array to store the decoded data. 00527 * @param buf_num Elements number of PCM buffer array. 00528 * 00529 * @returns 00530 * Elements number of decoded data. 00531 */ 00532 static uint32_t get_audio_data(flac_ctrl_t * const p_ctrl, 00533 int32_t * const p_buf, const uint32_t buf_num) 00534 { 00535 uint32_t read_cnt = 0u; 00536 bool result; 00537 00538 if ((p_ctrl != NULL) && (p_buf != NULL) && (buf_num > 0u)) { 00539 result = flac_set_pcm_buf(p_ctrl, p_buf, buf_num); 00540 while ((result == true) && ((read_cnt + MAX_SAMPLE_PER_1BLOCK) <= buf_num)) { 00541 result = flac_decode(p_ctrl); 00542 read_cnt = flac_get_pcm_cnt(p_ctrl); 00543 } 00544 } 00545 return read_cnt; 00546 } 00547 00548 /** Callback function of Audio Out Thread 00549 * 00550 * @param result Result of the process of Audio Out Thread 00551 */ 00552 static void data_out_callback(const bool result) 00553 { 00554 (void) send_mail(DEC_MAILID_CB_AUD_DATA_OUT, (uint32_t)result, MAIL_PARAM_NON); 00555 } 00556 00557 /** Callback function of SCUX driver 00558 * 00559 * @param p_data Pointer to PCM byffer array. 00560 * @param result Result of the process. 00561 * @param p_app_data The control ID of PCM buffer. 00562 */ 00563 static void write_callback(void * p_data, int32_t result, void * p_app_data) 00564 { 00565 const uint32_t buf_id = (uint32_t)p_app_data; 00566 bool flag_result; 00567 00568 UNUSED_ARG(p_data); 00569 if (result > 0) { 00570 flag_result = true; 00571 } else { 00572 flag_result = false; 00573 } 00574 (void) send_mail(DEC_MAILID_SCUX_WRITE_FIN, (uint32_t)flag_result, buf_id); 00575 } 00576 00577 /** Callback function of SCUX driver 00578 * 00579 * @param result Result of the process. 00580 */ 00581 static void flush_callback(int32_t result) 00582 { 00583 bool flag_result; 00584 00585 if (result > 0) { 00586 flag_result = true; 00587 } else { 00588 flag_result = false; 00589 } 00590 (void) send_mail(DEC_MAILID_SCUX_FLUSH_FIN, (uint32_t)flag_result, MAIL_PARAM_NON); 00591 } 00592 00593 /** Sends the mail to Decode thread 00594 * 00595 * @param mail_id Mail ID 00596 * @param param0 Parameter 0 of this mail 00597 * @param param1 Parameter 1 of this mail 00598 * 00599 * @returns 00600 * Results of process. true is success. false is failure. 00601 */ 00602 static bool send_mail(const DEC_MAIL_ID mail_id, 00603 const uint32_t param0, const uint32_t param1) 00604 { 00605 bool ret = false; 00606 osStatus stat; 00607 dec_mail_t * const p_mail = mail_box.alloc(); 00608 00609 if (p_mail != NULL) { 00610 p_mail->mail_id = mail_id; 00611 p_mail->param[MAIL_PARAM0] = param0; 00612 p_mail->param[MAIL_PARAM1] = param1; 00613 stat = mail_box.put(p_mail); 00614 if (stat == osOK) { 00615 ret = true; 00616 } else { 00617 (void) mail_box.free(p_mail); 00618 } 00619 } 00620 return ret; 00621 } 00622 00623 /** Receives the mail to Decode thread 00624 * 00625 * @param p_mail_id Pointer to the variable to store the mail ID 00626 * @param p_param0 Pointer to the variable to store the parameter 0 of this mail 00627 * @param p_param1 Pointer to the variable to store the parameter 1 of this mail 00628 * 00629 * @returns 00630 * Results of process. true is success. false is failure. 00631 */ 00632 static bool recv_mail(DEC_MAIL_ID * const p_mail_id, 00633 uint32_t * const p_param0, uint32_t * const p_param1) 00634 { 00635 bool ret = false; 00636 osEvent evt; 00637 dec_mail_t *p_mail; 00638 00639 if ((p_mail_id != NULL) && (p_param0 != NULL) && (p_param1 != NULL)) { 00640 evt = mail_box.get(); 00641 if (evt.status == osEventMail) { 00642 p_mail = (dec_mail_t *)evt.value.p; 00643 if (p_mail != NULL) { 00644 *p_mail_id = p_mail->mail_id; 00645 *p_param0 = p_mail->param[MAIL_PARAM0]; 00646 *p_param1 = p_mail->param[MAIL_PARAM1]; 00647 ret = true; 00648 } 00649 (void) mail_box.free(p_mail); 00650 } 00651 } 00652 return ret; 00653 } 00654 00655 /** Updates the status of Decode thread 00656 * 00657 * @param stat New status of Decode thread 00658 * @param p_play_info Pointer to the playback information of the playback file 00659 */ 00660 static void update_decode_stat(const SYS_PlayStat stat, play_info_t * const p_play_info) 00661 { 00662 if (p_play_info != NULL) { 00663 if (p_play_info->play_stat != stat) { 00664 p_play_info->play_stat = stat; 00665 notify_decode_stat(p_play_info); 00666 } 00667 } 00668 } 00669 00670 /** Updates the playback time 00671 * 00672 * @param play_time Current playback time 00673 * @param p_play_info Pointer to the playback information of the playback file 00674 */ 00675 static void update_decode_playtime(const uint32_t play_time, play_info_t * const p_play_info) 00676 { 00677 if (p_play_info != NULL) { 00678 if (p_play_info->play_time != play_time) { 00679 p_play_info->play_time = play_time; 00680 notify_decode_stat(p_play_info); 00681 } 00682 } 00683 } 00684 00685 /** Initialises the playback information 00686 * 00687 * @param total_time Total playback time 00688 * @param p_play_info Pointer to the playback information of the playback file 00689 */ 00690 static void init_decode_playinfo(const uint32_t total_time, play_info_t * const p_play_info) 00691 { 00692 if (p_play_info != NULL) { 00693 p_play_info->play_stat = SYS_PLAYSTAT_STOP; 00694 p_play_info->play_time = 0u; 00695 p_play_info->total_time = total_time; 00696 } 00697 } 00698 00699 /** Notifies Main thread of the status of Decode thread 00700 * 00701 * @param p_play_info Pointer to the playback information of the playback file 00702 */ 00703 static void notify_decode_stat(const play_info_t * const p_play_info) 00704 { 00705 if (p_play_info != NULL) { 00706 (void) sys_notify_play_time(p_play_info->play_stat, 00707 p_play_info->play_time, p_play_info->total_time); 00708 } 00709 }
Generated on Tue Jul 12 2022 22:07:08 by
 1.7.2