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

📄 mp3.cpp

📁 ICEExt for Driver Studio3.2的sourcecode
💻 CPP
字号:
/*++
    Copyright  (c) 2004 Sten
    Contact information:
        mail: stenri@mail.ru

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 
Module Name:
    mp3.cpp

Abstract: Helper mp3 decoding routines. 

Revision History:

 St        06/01/2004
      Initial release

--*/

extern "C" {
#pragma warning ( push, 3 )
#include <ntddk.h>
#pragma warning ( pop )
}

#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed
#pragma warning ( disable: 4127 ) // conditional expression is constant

#include <windef.h>
#include <ntverp.h>
#include <stdio.h>

#include "mp3.h"


/*
 * The following utility routine performs simple rounding, clipping, and
 * scaling of MAD's high-resolution samples down to 16 bits. It does not
 * perform any dithering or noise shaping, which would be recommended to
 * obtain any exceptional audio quality. It is therefore not recommended to
 * use this routine if high-quality output is desired.
 */

static inline signed int mp3_scale(mad_fixed_t sample)
{
    /* round */
    sample += (1L << (MAD_F_FRACBITS - 16));

    /* clip */
    if (sample >= MAD_F_ONE)
      sample = MAD_F_ONE - 1;
    else if (sample < -MAD_F_ONE)
      sample = -MAD_F_ONE;

    /* quantize */
    return sample >> (MAD_F_FRACBITS + 1 - 16);
}

/*
 * This is the output callback function. It is called after each frame of
 * MPEG audio data has been completely decoded. The purpose of this callback
 * is to output (or play) the decoded PCM audio.
 */
static int last_nsamples_left = 0;
static int bad_last_frame     = 0;

static int mp3_output(struct mad_header const *header,
	                  struct mad_pcm *pcm,
                      unsigned char *buf,
                      int  size)
{
	UNREFERENCED_PARAMETER(header);

    int out_size = 0;
    unsigned int nchannels, nsamples;
    mad_fixed_t const *left_ch, *right_ch;

    /* pcm->samplerate contains the sampling frequency */

    nchannels = pcm->channels;
    nsamples  = pcm->length;
    left_ch   = pcm->samples[0];
    right_ch  = pcm->samples[1];

    if (last_nsamples_left)
    {
        left_ch  += nsamples - last_nsamples_left;
        right_ch += nsamples - last_nsamples_left;
        nsamples = last_nsamples_left;
    }

    while (nsamples) 
    {
        signed int sample;

        nsamples--;

        // output sample(s) in 16-bit signed little-endian PCM 
        sample = mp3_scale(*left_ch++);

        if (out_size >= size) break;
        out_size += 2;

        *buf++ = (UCHAR)((sample >> 0) & 0xff);
        *buf++ = (UCHAR)((sample >> 8) & 0xff);

        if (nchannels == 2) 
        {
            if (out_size >= size) break;
            out_size += 2;

            sample = mp3_scale(*right_ch++);
            *buf++ = (UCHAR)((sample >> 0) & 0xff);
            *buf++ = (UCHAR)((sample >> 8) & 0xff);
        }
    }

    last_nsamples_left = nsamples;

    return out_size;
}

/*
 * This is the error callback function. It is called whenever a decoding
 * error occurs. The error is indicated by stream->error; the list of
 * possible MAD_ERROR_* errors can be found in the mad.h (or
 * libmad/stream.h) header file.
 */
static enum mad_flow mp3_error(struct mad_stream *stream,
		               struct mad_frame *frame)
{
    DbgPrint("decoding error 0x%04x (%s) at offset %u\n",
  	    stream->error, mad_stream_errorstr(stream),
	    (PUCHAR)stream->this_frame - (PUCHAR)stream->buffer);

    switch (stream->error) 
    {
        case MAD_ERROR_BADCRC:
                    if (bad_last_frame)
                        mad_frame_mute(frame);
                    else
                        bad_last_frame = 1;

                    return MAD_FLOW_IGNORE;

        default:
                    return MAD_FLOW_IGNORE;
    }
}

static struct mad_stream stream;
static struct mad_frame  frame;
static struct mad_synth  synth;

void mp3_Init(void *mp3buf, int size)
{
    last_nsamples_left = 0;
    bad_last_frame     = 0;

    mad_stream_init(&stream);
    mad_frame_init(&frame);
    mad_synth_init(&synth);

    mad_stream_options(&stream, 0);
    mad_stream_buffer(&stream, (const unsigned char *)mp3buf, size); 
}

void mp3_Done()
{
    mad_synth_finish(&synth);
    mad_frame_finish(&frame);
    mad_stream_finish(&stream);
}

int mp3_GetData(unsigned char *buf, int size)
{
    int out_size = 0;

    if (mp3_EOF()) return -1;

    memset(buf, 0, size);
    while (1) 
    {
        int delta = mp3_output(&frame.header, &synth.pcm, buf, size - out_size); 
        out_size += delta;
        buf      += delta;
        if (out_size >= size) break;

        if (mad_header_decode(&frame.header, &stream) == -1) 
        {
	    if (!MAD_RECOVERABLE(stream.error)) return -1;

	    switch (mp3_error(&stream, &frame)) 
            {
	        case MAD_FLOW_STOP:
	                           return -1;
	         
                case MAD_FLOW_BREAK:
	                           return -1;
	          
                case MAD_FLOW_IGNORE:
	        case MAD_FLOW_CONTINUE:
	        default:
	                           continue;
            }
	}

        if (mad_frame_decode(&frame, &stream) == -1) 
        {
   	    if (!MAD_RECOVERABLE(stream.error)) return -1;

            switch (mp3_error(&stream, &frame)) 
            {
	        case MAD_FLOW_STOP:
	                           return -1;
          	
                case MAD_FLOW_BREAK:
	                           return -1;
	        
                case MAD_FLOW_IGNORE:
	                           break;
	 
                case MAD_FLOW_CONTINUE:
                default:
	                           continue;
            }
        }
        else
            bad_last_frame = 0;

        mad_synth_frame(&synth, &frame);
    }
    return out_size;
}

int mp3_GetCurrentSampleRate()
{
    return  (frame.header.samplerate * synth.pcm.channels) / 2; // we always play stereo sound
}

bool mp3_EOF()
{
    return stream.this_frame >= stream.bufend;
}

void mp3_RestartStream()
{
    last_nsamples_left = 0;
    bad_last_frame     = 0;
    mad_stream_buffer(&stream, stream.buffer, (PUCHAR)stream.bufend - (PUCHAR)stream.buffer); 
}

⌨️ 快捷键说明

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