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 Renesas

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dec_flac.cpp Source File

dec_flac.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 "decode.h"
00025 #include "misratypes.h"
00026 #include "dec_flac.h"
00027 
00028 static FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, 
00029                             FLAC__byte buffer[], size_t *bytes, void *client_data);
00030 static FLAC__StreamDecoderWriteStatus write_cb (const FLAC__StreamDecoder *decoder,
00031     const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data);
00032 static void meta_cb(const FLAC__StreamDecoder *decoder, 
00033                             const FLAC__StreamMetadata *metadata, void *client_data);
00034 static void error_cb(const FLAC__StreamDecoder *decoder, 
00035                             FLAC__StreamDecoderErrorStatus status, void *client_data);
00036 static void init_ctrl_data(flac_ctrl_t * const p_ctrl);
00037 static bool check_file_spec(const flac_ctrl_t * const p_ctrl);
00038 static bool check_end_of_stream(const flac_ctrl_t * const p_flac_ctrl);
00039 
00040 bool flac_set_pcm_buf(flac_ctrl_t * const p_flac_ctrl, 
00041                         int32_t * const p_buf_addr, const uint32_t buf_num)
00042 {
00043     bool        ret = false;
00044     if ((p_flac_ctrl != NULL) && (p_buf_addr != NULL) && (buf_num > 0u)) {
00045         p_flac_ctrl->p_pcm_buf = p_buf_addr;
00046         p_flac_ctrl->pcm_buf_num = buf_num;
00047         p_flac_ctrl->pcm_buf_used_cnt = 0u;
00048         ret = true;
00049     }
00050     return ret;
00051 }
00052 
00053 uint32_t flac_get_pcm_cnt(const flac_ctrl_t * const p_flac_ctrl)
00054 {
00055     uint32_t    ret = 0u;
00056     if (p_flac_ctrl != NULL) {
00057         ret = p_flac_ctrl->pcm_buf_used_cnt;
00058     }
00059     return ret;
00060 }
00061 
00062 uint32_t flac_get_play_time(const flac_ctrl_t * const p_flac_ctrl)
00063 {
00064     uint32_t    play_time = 0u;
00065     if (p_flac_ctrl != NULL) {
00066         if (p_flac_ctrl->sample_rate > 0u) {    /* Prevents division by 0 */
00067             play_time = (uint32_t)(p_flac_ctrl->decoded_sample / p_flac_ctrl->sample_rate);
00068         }
00069     }
00070     return play_time;
00071 }
00072 
00073 uint32_t flac_get_total_time(const flac_ctrl_t * const p_flac_ctrl)
00074 {
00075     uint32_t    total_time = 0u;
00076     if (p_flac_ctrl != NULL) {
00077         if (p_flac_ctrl->sample_rate > 0u) {    /* Prevents division by 0 */
00078             total_time = (uint32_t)(p_flac_ctrl->total_sample / p_flac_ctrl->sample_rate);
00079         }
00080     }
00081     return total_time;
00082 }
00083 
00084 bool flac_open(FILE * const p_handle, flac_ctrl_t * const p_flac_ctrl)
00085 {
00086     bool                            ret = false;
00087     FLAC__bool                      result;
00088     FLAC__StreamDecoderInitStatus   result_init;
00089     FLAC__StreamDecoder             *p_dec;
00090     
00091     if ((p_handle != NULL) && (p_flac_ctrl != NULL)) {
00092         /* Initialises Internal memory */
00093         init_ctrl_data(p_flac_ctrl);
00094         p_flac_ctrl->p_file_handle = p_handle;
00095         /* Creates the instance of flac decoder. */
00096         p_dec = FLAC__stream_decoder_new();
00097         if (p_dec != NULL) {
00098             /* Sets the MD5 check. */
00099             (void) FLAC__stream_decoder_set_md5_checking(p_dec, true);
00100             /* Initialises the instance of flac decoder. */
00101             result_init = FLAC__stream_decoder_init_stream(p_dec, &read_cb, NULL, NULL, 
00102                             NULL, NULL, &write_cb, &meta_cb, &error_cb, (void *)p_flac_ctrl);
00103             if (result_init == FLAC__STREAM_DECODER_INIT_STATUS_OK) {
00104                 /* Decodes until end of metadata. */
00105                 result = FLAC__stream_decoder_process_until_end_of_metadata(p_dec);
00106                 if (result == true) {
00107                     if (check_file_spec(p_flac_ctrl) == true) {
00108                         p_flac_ctrl->p_decoder = p_dec;
00109                         ret = true;
00110                     }
00111                 }
00112             }
00113             if (ret != true) {
00114                 FLAC__stream_decoder_delete(p_dec);
00115             }
00116         }
00117     }
00118     return ret;
00119 }
00120 
00121 bool flac_decode(const flac_ctrl_t * const p_flac_ctrl)
00122 {
00123     bool            ret = false;
00124     bool            eos;
00125     FLAC__bool      result;
00126     uint32_t        used_cnt;
00127 
00128     if (p_flac_ctrl != NULL) {
00129         eos = check_end_of_stream(p_flac_ctrl);
00130         if (eos != true) {
00131             /* Decoding position is not end of stream. */
00132             used_cnt = p_flac_ctrl->pcm_buf_used_cnt;
00133             result = FLAC__stream_decoder_process_single (p_flac_ctrl->p_decoder);
00134             if (result == true) {
00135                 /* Did a decoded data increase? */
00136                 if (p_flac_ctrl->pcm_buf_used_cnt > used_cnt) {
00137                     /* FLAC decoder process succeeded. */
00138                     ret = true;
00139                 }
00140             }
00141         }
00142     }
00143     return ret;
00144 }
00145 
00146 void flac_close(flac_ctrl_t * const p_flac_ctrl)
00147 {
00148     if (p_flac_ctrl != NULL) {
00149         FLAC__stream_decoder_delete(p_flac_ctrl->p_decoder);
00150         p_flac_ctrl->p_decoder = NULL;
00151     }
00152 }
00153 
00154 /** Read callback function of FLAC decoder library
00155  *
00156  *  @param decoder Decoder instance.
00157  *  @param buffer Pointer to the buffer to store the data of FLAC file.
00158  *  @param bytes Pointer to the size of the buffer.
00159  *  @param client_data Pointer to the control data of FLAC module.
00160  *
00161  *  @returns 
00162  *    Results of process. Returns the following status.
00163  *    FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
00164  *    FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
00165  *    FLAC__STREAM_DECODER_READ_STATUS_ABORT
00166  */
00167 static FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, 
00168                             FLAC__byte buffer[], size_t *bytes, void *client_data)
00169 {
00170     FLAC__StreamDecoderReadStatus   ret = FLAC__STREAM_DECODER_READ_STATUS_ABORT;
00171     flac_ctrl_t                     * const p_ctrl = (flac_ctrl_t*)client_data;
00172     size_t                          read_size;
00173 
00174     UNUSED_ARG(decoder);
00175     if ((buffer != NULL) && (bytes != NULL) && (p_ctrl != NULL)) {
00176         if (*bytes > 0u) {
00177             read_size = fread(&buffer[0], sizeof(FLAC__byte), *bytes, p_ctrl->p_file_handle);
00178             if (read_size > 0u) {
00179                 ret = FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
00180                 *bytes = read_size;
00181             } else {
00182                 ret = FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
00183                 *bytes = 0;
00184             }
00185         }
00186     }
00187     return ret;
00188 }
00189 
00190 /** Write callback function of FLAC decoder library
00191  *
00192  *  @param decoder Decoder instance.
00193  *  @param frame The description of the decoded frame.
00194  *  @param buffer Pointer to the decoded data.
00195  *  @param client_data Pointer to the control data of FLAC module.
00196  *
00197  *  @returns 
00198  *    Results of process. Returns the following status.
00199  *    FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
00200  *    FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
00201  */
00202 static FLAC__StreamDecoderWriteStatus write_cb (const FLAC__StreamDecoder *decoder,
00203         const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
00204 {
00205     FLAC__StreamDecoderWriteStatus  ret = FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
00206     const FLAC__int32               *p_ch0;
00207     const FLAC__int32               *p_ch1;
00208     flac_ctrl_t                     *const p_ctrl = (flac_ctrl_t*)client_data;
00209     uint32_t                        bit_shift_num;
00210     uint32_t                        i;
00211 
00212     UNUSED_ARG(decoder);
00213     if ((frame != NULL) && (buffer != NULL) && (p_ctrl != NULL)) {
00214         if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER) {
00215             p_ctrl->decoded_sample = frame->header.number.sample_number + frame->header.blocksize;
00216         } else {
00217             p_ctrl->decoded_sample += frame->header.blocksize;
00218         }
00219         if (p_ctrl->p_pcm_buf == NULL) {
00220             /* Error */
00221         } else if (frame->header.blocksize > DEC_MAX_BLOCK_SIZE) {
00222             /* Error : Block size is illegal specification */
00223         } else {
00224             bit_shift_num = (DEC_OUTPUT_BITS_PER_SAMPLE + DEC_OUTPUT_PADDING_BITS)- p_ctrl->bits_per_sample;
00225             if (p_ctrl->channel_num == DEC_MAX_CHANNEL_NUM) {
00226                 /* stereo */
00227                 p_ch0 = buffer[0];
00228                 p_ch1 = buffer[1];
00229             } else {
00230                 /* mono */
00231                 p_ch0 = buffer[0];
00232                 p_ch1 = buffer[0];
00233             }
00234             if ((p_ctrl->pcm_buf_num - p_ctrl->pcm_buf_used_cnt) >= (frame->header.blocksize * DEC_MAX_CHANNEL_NUM)) {
00235                 for (i = 0; i < frame->header.blocksize; i++) {
00236                     /* ch 0 */
00237                     p_ctrl->p_pcm_buf[p_ctrl->pcm_buf_used_cnt] = (int32_t)((uint32_t)p_ch0[i] << bit_shift_num);
00238                     p_ctrl->pcm_buf_used_cnt++;
00239                     /* ch 1 */
00240                     p_ctrl->p_pcm_buf[p_ctrl->pcm_buf_used_cnt] = (int32_t)((uint32_t)p_ch1[i] << bit_shift_num);
00241                     p_ctrl->pcm_buf_used_cnt++;
00242                 }
00243                 ret = FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
00244             }
00245         }
00246     }
00247     return ret;
00248 }
00249 
00250 /** Metadata callback function of FLAC decoder library
00251  *
00252  *  @param decoder Decoder instance.
00253  *  @param metadata Block of the decoded metadata.
00254  *  @param client_data Pointer to the control data of FLAC module.
00255  */
00256 static void meta_cb(const FLAC__StreamDecoder *decoder, 
00257             const FLAC__StreamMetadata *metadata, void *client_data)
00258 {
00259     flac_ctrl_t     *const p_ctrl = (flac_ctrl_t*)client_data;
00260 
00261     UNUSED_ARG(decoder);
00262     if ((metadata != NULL) && (p_ctrl != NULL)) {
00263         if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
00264             p_ctrl->sample_rate = metadata->data.stream_info.sample_rate;
00265             p_ctrl->channel_num = metadata->data.stream_info.channels;
00266             p_ctrl->bits_per_sample = metadata->data.stream_info.bits_per_sample;
00267             p_ctrl->total_sample = metadata->data.stream_info.total_samples;
00268         }
00269     }
00270 }
00271 
00272 /** Error callback function of FLAC decoder library
00273  *
00274  *  @param decoder Decoder instance.
00275  *  @param client_data Pointer to the control data of FLAC module.
00276  */
00277 static void error_cb(const FLAC__StreamDecoder *decoder, 
00278             FLAC__StreamDecoderErrorStatus status, void *client_data)
00279 {
00280     /* DO NOTHING */
00281     UNUSED_ARG(decoder);
00282     UNUSED_ARG(status);
00283     UNUSED_ARG(client_data);
00284 }
00285 
00286 /** Initialises the control data of FLAC module
00287  *
00288  *  @param p_ctrl Pointer to the control data of FLAC module.
00289  */
00290 static void init_ctrl_data(flac_ctrl_t * const p_ctrl)
00291 {
00292     if (p_ctrl != NULL) {
00293         p_ctrl->p_decoder        = NULL;    /* Handle of flac decoder */
00294         p_ctrl->p_file_handle    = NULL;    /* Handle of flac file */
00295         p_ctrl->decoded_sample   = 0uLL;    /* Number of a decoded sample */
00296         p_ctrl->total_sample     = 0uLL;    /* Total number of sample */
00297         p_ctrl->sample_rate      = 0u;      /* Sample rate in Hz */
00298         p_ctrl->channel_num      = 0u;      /* Number of channels */
00299         p_ctrl->bits_per_sample  = 0u;      /* bit per sample */
00300         p_ctrl->p_pcm_buf        = NULL;    /* Pointer of PCM buffer */
00301         p_ctrl->pcm_buf_num      = 0u;      /* Number of elements in PCM buffer */
00302         p_ctrl->pcm_buf_used_cnt = 0u;      /* Counter of used elements in PCM buffer */
00303     }
00304 }
00305 
00306 /** Checks the playable file of the playback
00307  *
00308  *  @param client_data Pointer to the control data of FLAC module.
00309  */
00310 static bool check_file_spec(const flac_ctrl_t * const p_ctrl)
00311 {
00312     bool    ret = false;
00313 
00314     if (p_ctrl == NULL) {
00315         /* Error : NULL pointer */
00316     } else if ((p_ctrl->channel_num <= 0u) || 
00317                (p_ctrl->channel_num > DEC_MAX_CHANNEL_NUM)) {
00318         /* Error : Channel number is illegal specification */
00319     } else if ((p_ctrl->bits_per_sample != DEC_16BITS_PER_SAMPLE) && 
00320                (p_ctrl->bits_per_sample != DEC_24BITS_PER_SAMPLE)) {
00321         /* Error : Bit per sample is illegal specification */
00322     } else if ((p_ctrl->sample_rate < DEC_INPUT_MIN_SAMPLE_RATE) || 
00323                (p_ctrl->sample_rate > DEC_INPUT_MAX_SAMPLE_RATE)) {
00324         /* Error : Sample rate is illegal specification */
00325     } else {
00326         /* OK */
00327         ret = true;
00328     }
00329     return ret;
00330 }
00331 
00332 /** Checks the state of the FLAC decoder
00333  *
00334  *  @param p_flac_ctrl Pointer to the control data of FLAC module.
00335  *
00336  *  @returns 
00337  *    The state of FLAC decoder. true is end of stream. false is other state.
00338  */
00339 static bool check_end_of_stream(const flac_ctrl_t * const p_flac_ctrl)
00340 {
00341     bool                        ret = false;
00342     FLAC__StreamDecoderState    state;
00343 
00344     if (p_flac_ctrl != NULL) {
00345         state = FLAC__stream_decoder_get_state(p_flac_ctrl->p_decoder);
00346         if (state == FLAC__STREAM_DECODER_END_OF_STREAM) {
00347             ret = true;
00348         }
00349     }
00350     return ret;
00351 }