⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pflac_dec.c

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 C
字号:
/* Copyright (C) 2007 ROCK-CHIPS FUZHOU . All Rights Reserved. */
/*
File : \Audio\FLACDec
Desc : FLAC解码。

Author : huangxd , Vincent Hisung
Date : 2007-08-xx
Notes :

$Log :
* huangxd     2007/08/xx 建立此文件
*
* vincent            2007/08/xx 修订完善
*
* huaugxd,vincent    2007/09/xx 增加INFO信息支持
*
*/
/****************************************************************/

#include "../include/audio_main.h"

#ifdef FLAC_DEC_INCLUDE

#include "../include/audio_globals.h"
#include "../include/file_access.h"
#include "pFLAC_DEC.h"

extern void *Flac_pclient_data ;
extern FLAC__BitBuffer *Flac_pinput ;
extern void *Flac_pReadBack ;
extern unsigned char* Flac_pInBuffer;//指向输入缓冲首地址
extern unsigned char* Flac_pPcmLeft;
extern unsigned char* Flac_pPcmRight;
extern FILE* Flac_fpInFileName;
extern unsigned long  Flac_gSampleRate;
extern unsigned char  Flac_gChannels;
extern unsigned long  Flac_gBitRate;
extern unsigned long  Flac_gTimeLength;
extern unsigned long  Flac_gLength;
extern tFLACFileIo    Flac_gFileOper;//定义文件操作结构体变量,成员为指向回调函数的函数指针
extern int Flac_gNumofSeekTablePoints;
extern int Flac_gCurUsedSeekTablePoints; // 当时快进快退的点
extern FLAC__StreamMetadata_SeekPoint Flac_gSeekTablePoints[MAX__SEEK_POINTS_NUM];
extern int Flac_gFlagRealloc ; // 快进快退的标记
unsigned char* Flac_pArtist;
unsigned char* Flac_pAlbum;
unsigned char* Flac_pTitle;
unsigned char* Flac_pGenre;
unsigned char* Flac_pDate;
unsigned char* Flac_pComment;
unsigned char* Flac_pTrackNumber;

static short *flac_OutLeft = NULL;//[FLAC_PCM_BUFFER_SIZE];
static short *flac_OutRight = NULL;//[FLAC_PCM_BUFFER_SIZE];

static long OutLength;

extern int flac_block_decoder_decframe(void);
extern int flac_block_decoder_finish(void);

//****************************************************************************
//
// The codec plug-in entry point for the FLAC decoder.
//
//****************************************************************************
//功能实现情况:
//SUBFN_CODEC_GETNAME  :   不支持
//SUBFN_CODEC_GETARTIST:   得到艺术家名
//SUBFN_CODEC_GETTITLE :   得到曲名
//SUBFN_CODEC_GETBITRATE:  得到码率
//SUBFN_CODEC_GETSAMPLERATE: 得到采样率
//SUBFN_CODEC_GETCHANNELS: 得到声道数目
//SUBFN_CODEC_GETLENGTH :  得到时长 [单位:毫秒]
//SUBFN_CODEC_GETTIME  :   得到当前播放时间 [单位:毫秒]
//SUBFN_CODEC_OPEN_DEC :   打开解码器(初始化)
//SUBFN_CODEC_DECODE   :   解码
//SUBFN_CODEC_ENCODE   :   不支持
//SUBFN_CODEC_SEEK     :   按时间直接定位 [单位:毫秒]
//SUBFN_CODEC_CLOSE    :   关闭解码器

/******************************************************
Name:  FLACDecFunction
Desc:  FLAC解码器接口函数
Param: ulIoctl 子功能号
    ulParam1 子功能参数1
    ulParam2 子功能参数2
    ulParam3 子功能参数3
    ulParam4 子功能参数4

Return: 0-失败 1-成功
Global: 无
Note: 无
Author: HXD
Log:
******************************************************/
int FlacBlockSize;

unsigned long
FLACDecFunction(unsigned long ulSubFn, unsigned long ulParam1, unsigned long ulParam2,
                unsigned long ulParam3, unsigned long ulParam4)
{
    unsigned int WaitCounter = 0;

    switch (ulSubFn)
    {

            // Decode a frame of data.
        case SUBFN_CODEC_DECODE:
            {

                tFLAC *pFLAC;
                short *psLeft, *psRight;
                long  lLength;
                int   decStatus = 0;

                pFLAC = (tFLAC *)ulParam1;

                //解码结束标记就是当decStatus等于2,退出
                decStatus = flac_block_decoder_decframe(); //0表示解码正确且不是最后一帧,2表示解码结束或读文件出错,1表示解码出错且填0于输出缓冲;



                //输出----------------------------------
                {
                    int i;


                    OutLength = FlacBlockSize;// lLength - 4;
                    if (OutLength == 0)
                        OutLength = 4096;

  if(Flac_gChannels==2)
       {  
                    for (i = 0;i < OutLength;i++)
                    {
                        flac_OutLeft[i] = pFLAC->psLeft[2*i];
                        flac_OutRight[i] = pFLAC->psRight[2*i];
                    }
          }
          else if( Flac_gChannels==1)
          {
                   for (i = 0;i < OutLength;i++)
                    {
                        flac_OutLeft[i] = pFLAC->psLeft[2*i];
                        flac_OutRight[i] =  flac_OutLeft[i] ;
                    }

          }
                }
                //---------------------------------------

                if (decStatus == 2)//由于解码内部0表示解码正确,1表示解码错误,2表示解码结束;但解码外部0表示错误,1和2表示正确,故我们需要转换以下返回值
                {
                    return 0;
                }
                else
                {
                    pFLAC->ulTimePos += OutLength;
                    return 1;
                }

            }

            // Prepare the codec to decode a file.
        case SUBFN_CODEC_OPEN_DEC:
            {
                tFLAC* pFLAC;
                // The first parameter is a pointer to the FLAC persistent data.
                pFLAC = (tFLAC *)ulParam1;

                //获取采样率,比特率,声道,文件时间总长度
                pFLAC->usSampleRate = Flac_gSampleRate;
                pFLAC->ucChannels = Flac_gChannels;
                pFLAC->ulBitRate = Flac_gBitRate;
                pFLAC->ulTimeLength = Flac_gTimeLength;//单位为毫秒
                pFLAC->ulLength = Flac_gLength;//单位为Bytes
                pFLAC->ulTimePos = 0;

                flac_OutLeft = (short *) malloc(FLAC_PCM_BUFFER_SIZE * sizeof(short));
                flac_OutRight = (short *) malloc(FLAC_PCM_BUFFER_SIZE * sizeof(short));
                return 1;
            }

            // Seek to the specified time position.
        case SUBFN_CODEC_SEEK:
            {

                tFLAC *pFLAC;
                unsigned long  ulPos;
                unsigned long  ulFileOffset;

                // The first parameter is a pointer to the FLAC persistent data.
                pFLAC = (tFLAC *)ulParam1;
                if (ulParam2 > pFLAC->ulTimeLength)//ulParam2单位是毫秒,ulTimeLength单位也是毫秒
                {
                    ulParam2 = pFLAC->ulTimeLength;
                }

                // Compute the number of frames that occur before the requested
                // time position.

                // Compute the time for the computed frame number.
                pFLAC->ulTimePos = ulPos = ((ulParam2 / 1000) * pFLAC->usSampleRate) + (((ulParam2 % 1000) * pFLAC->usSampleRate) / 1000);//计算当前位置的对应的样本数目

                // Compute the number of seek table points and the file position based on the actual seek time.
                Flac_gCurUsedSeekTablePoints = 0;
                while ((ulPos >= (unsigned long)Flac_gSeekTablePoints[Flac_gCurUsedSeekTablePoints].sample_number) && (Flac_gCurUsedSeekTablePoints < Flac_gNumofSeekTablePoints))
                {
                    Flac_gCurUsedSeekTablePoints++;
                }

                if (Flac_gSeekTablePoints[Flac_gCurUsedSeekTablePoints].stream_offset == 0)
                {
                    if (Flac_gCurUsedSeekTablePoints > 0)
                        Flac_gCurUsedSeekTablePoints--;
                }
                if (Flac_gCurUsedSeekTablePoints != 0)
                {
                    pFLAC->ulTimePos = Flac_gSeekTablePoints[Flac_gCurUsedSeekTablePoints].sample_number;

                    //计算当前时间点对应的文件位置,单位为字节
                    ulFileOffset = (unsigned long)Flac_gSeekTablePoints[Flac_gCurUsedSeekTablePoints].stream_offset;

                }
                else
                    ulFileOffset = pFLAC->ulBitRate * (ulParam2 / 8);

                if (ulFileOffset >= Flac_gLength)
                    ulFileOffset = Flac_gLength;

                RKFIO_FSeek((MY_FILE*)Flac_fpInFileName, ulFileOffset, SEEK_SET);

                /*
                if(RKFIO_FSeek((MY_FILE*)Flac_fpInFileName, ulFileOffset, SEEK_SET) != 0)
                {
                return 0;
                }
                */
                Flac_gFlagRealloc = true;

                return(1);
            }

            // Return the current position (in milliseconds) within the file.
        case SUBFN_CODEC_GETTIME:
            {
                unsigned long *pulTime;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the MP3 persistent data.
                pFLAC = (tFLAC *)ulParam1;

                // The second parameter is a pointer for the number of seconds.
                pulTime = (unsigned long *)ulParam2;

                if (pFLAC->usSampleRate)
                {
                    // Determine the time based on the sample rate.
                    *pulTime = ((pFLAC->ulTimePos / pFLAC->usSampleRate) * 1000) +
                               (((pFLAC->ulTimePos % pFLAC->usSampleRate) * 1000) /
                                pFLAC->usSampleRate);
                }

                // Success.
                return(1);
            }

            // Return the sample rate at which this file is encoded.
        case SUBFN_CODEC_GETSAMPLERATE:
            {
                unsigned long *pulSampleRate;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the MP3 persistent data.
                pFLAC = (tFLAC *)ulParam1;

                pulSampleRate = (unsigned long *)ulParam2;

                // Return the sample rate of the file.
                *pulSampleRate = pFLAC->usSampleRate;

                // Success.
                return(1);
            }

            // Return the number of channels in the file.
        case SUBFN_CODEC_GETCHANNELS:
            {
                unsigned long *pulChannels;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the MP3 persistent data.
                pFLAC = (tFLAC *)ulParam1;

                pulChannels = (unsigned long *)ulParam2;

                // Return the number of channels in the file.
                *pulChannels = pFLAC->ucChannels;

                // Success.
                return(1);
            }

            // Return the bitrate at which this file is encoded.
        case SUBFN_CODEC_GETBITRATE:
            {
                unsigned long *pulBitRate;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the MP3 persistent data.
                pFLAC = (tFLAC *)ulParam1;

                pulBitRate = (unsigned long *)ulParam2;

                // Return the number of channels in the file.
                *pulBitRate = pFLAC->ulBitRate * 1000;
                // Success.
                return(1);
            }

            // Return the length (in milliseconds) of the file.
        case SUBFN_CODEC_GETLENGTH:
            {
                unsigned long *pulLength;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the APE persistent data.
                pFLAC = (tFLAC *)ulParam1;

                pulLength = (unsigned long *)ulParam2;

                // Return the length of the file.
                *pulLength = pFLAC->ulTimeLength;

                // Success.
                return(1);
            }

        case SUBFN_CODEC_GETCAPTUREBUFFER:
            {
                *(unsigned long *)ulParam2 = (unsigned long) flac_OutLeft ;
                *(unsigned long *)ulParam3 = (unsigned long) flac_OutRight;
                *(unsigned long *)ulParam4 = (unsigned long) OutLength ;

                return(1);
            }
            // Return the name of the artist.
        case SUBFN_CODEC_GETARTIST:
            {
                char **ppcName;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the FLAC persistent data.
                pFLAC = (tFLAC *)ulParam1;

                // The second parameter is a pointer for the name.
                ppcName = (char **)ulParam2;

                // Return the name of the artist.
                *ppcName = (char *)pFLAC->ucArtist;

                // Success.
                return(1);
            }

            // Return the name of the song
        case SUBFN_CODEC_GETTITLE:
            {
                char **ppcName;
                tFLAC *pFLAC;

                // The first parameter is a pointer to the FLAC persistent data.
                pFLAC = (tFLAC *)ulParam1;

                // The second parameter is a pointer for the name.
                ppcName = (char **)ulParam2;

                // Return the name of the song.
                *ppcName = (char *)pFLAC->ucTitle;

                // Success.
                return(1);
            }


            // Cleanup after the codec.
        case SUBFN_CODEC_CLOSE:
            {
                tFLAC *pFLAC;
                pFLAC = (tFLAC *) ulParam1;

                pFLAC->status = flac_block_decoder_finish() ;
                if (flac_OutLeft != NULL)
                {
                    free(flac_OutLeft);
                    flac_OutLeft = NULL;
                }
                if (flac_OutRight != NULL)
                {
                    free(flac_OutRight);
                    flac_OutRight = NULL;
                }

                if (pFLAC->status == 0)//0表示正常结束,否则错误结束
                {
                    return(1);
                }
                else
                {
                    return(0);
                }
            }

        default:
            {
                // Return a failure.
                return(0);
            }
    }
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -