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

📄 wavplugin.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include <stdio.h>#include <stdarg.h>#include <stdlib.h>#include <errno.h>#include <qfile.h>#include "wavplugin.h"#ifndef Q_OS_WIN32#include <unistd.h>#endifextern "C" {#include "gsm.h"};//#define debugMsg(a)	    qDebug(a)#define debugMsg(a)#ifndef Q_OS_WIN32// Win32 has a different name for the same function# define strncasecmp strncmp	# include <endian.h># if __BYTE_ORDER == __BIG_ENDIAN#  define IS_BIG_ENDIAN# endif#endifstruct RiffChunk {    char id[4];    Q_UINT32 size;    char data[4];};struct ChunkData {    Q_INT16 formatTag;    Q_INT16 channels;    Q_INT32 samplesPerSec;    Q_INT32 avgBytesPerSec;    Q_INT16 blockAlign;    Q_INT16 wBitsPerSample;};struct GsmExtHeader {    Q_INT16 wExtSize;    Q_INT16 samplesPerBlock;};#ifdef IS_BIG_ENDIANQ_INT32 swap32( Q_INT32 w ){    unsigned char *c = (unsigned char *)&w;    // Swap byte 1 and 4    unsigned char t = *c;    *c = *(c+3);    *(c+3) = t;    // Swap byte 2 and 3    c++;    t = *c;    *c = *(c+1);    *(c+1) = t;    return w;}inline Q_INT16 swap16( Q_INT16 s ){    unsigned char *c = (unsigned char *)&s;    unsigned char t = *c;    *c = *(c+1);    *(c+1) = t;        return s;}void swapRiffChunk( RiffChunk *r ){    r->size = swap32(r->size);}void swapChunkData( ChunkData *d ){    d->formatTag = swap16(d->formatTag);    d->channels = swap16(d->channels);    d->samplesPerSec = swap32(d->samplesPerSec);    d->avgBytesPerSec = swap32(d->avgBytesPerSec);    d->blockAlign = swap16(d->blockAlign);    d->wBitsPerSample = swap16(d->wBitsPerSample);}void swapGsmExtHeader( GsmExtHeader *h ){    h->wExtSize = swap16(h->wExtSize);    h->samplesPerBlock = swap16(h->samplesPerBlock);}#elseinline Q_INT32 swap32( Q_INT32 w ) { return w; }inline Q_INT16 swap16( Q_INT16 s ) { return s; }inline void swapRiffChunk( RiffChunk * ) {}inline void swapChunkData( ChunkData * ) {}inline void swapGsmExtHeader( GsmExtHeader * ) {}#endifconst int sound_buffer_size = 4096;#define WAVE_FORMAT_PCM    1#define WAVE_FORMAT_GSM610 0x31class WavPluginData {public:    QFile *input;    int wavedata_remaining;    ChunkData chunkdata;    GsmExtHeader gsmext;    RiffChunk chunk;    uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data    int out,max;    int samples_due;    int samples;    gsm gsmhandle;    gsm_signal gsmsamples[320];    int gsmnext;    WavPluginData() {	input = 0;	max = out = sound_buffer_size;	wavedata_remaining = 0;	samples_due = 0;	samples = -1;	gsmhandle = 0;	gsmnext = 320;    }    ~WavPluginData() {	if ( gsmhandle ) {	    gsm_destroy( gsmhandle );	}    }    // expands out samples to the frequency of 44kHz    bool add( short *output, long count, long& done, bool stereo )    {	done = 0;	if ( input == 0 ) {	    qDebug("no input");	    return FALSE;	}	if ( chunkdata.formatTag == WAVE_FORMAT_PCM ) {	    // read PCM samples	    while ( count ) {		int l,r;		if ( getSample(l, r) == FALSE ) {		    // Make the loopcontrol think we played to the end		    done = count;		    return FALSE;		}		samples_due += 44100;		while ( count && ( samples_due >= chunkdata.samplesPerSec ) ) {		    *output++ = l;		    if ( stereo )			*output++ = r;		    samples_due -= chunkdata.samplesPerSec;		    count--;		    done++;		}	    }        } else {	    // read GSM samples	    while ( count ) {		int samp;		if ( gsmnext < 320 ) {		    samp = gsmsamples[gsmnext++];		} else if ( nextGsmBlock() ) {		    samp = gsmsamples[gsmnext++];		} else {		    // Make the loopcontrol think we played to the end		    done = count;		    return FALSE;		}		samples_due += 44100;		while ( count && ( samples_due >= chunkdata.samplesPerSec ) ) {		    *output++ = samp;		    if ( stereo )			*output++ = samp;		    samples_due -= chunkdata.samplesPerSec;		    count--;		    done++;		}	    }	}        return TRUE;    }    bool initialise() {	if ( input == 0 )	    return FALSE;	if ( gsmhandle ) {	    gsm_destroy( gsmhandle );	    gsmhandle = 0;	}	wavedata_remaining = -1;	while ( wavedata_remaining == -1 ) {	    // Keep reading chunks...	    const int n = sizeof(chunk) - sizeof(chunk.data);	    int t = input->readBlock( (char*)&chunk, n );	    if ( t != n ) {		if ( t == -1 )		    return FALSE;		return TRUE;	    }	    swapRiffChunk(&chunk);	    if ( qstrncmp(chunk.id,"data",4) == 0 ) { // No tr		wavedata_remaining = chunk.size;		// approx. number of 44.1KHz samples		if ( chunkdata.formatTag == WAVE_FORMAT_GSM610 ) {		    samples = (wavedata_remaining / 65) * 320;		    samples = samples * 441 / (chunkdata.samplesPerSec/100);		} else {		    samples = wavedata_remaining / chunkdata.channels;		    if ( chunkdata.wBitsPerSample == 16 )			samples /= 2;		    samples = samples * 441 / (chunkdata.samplesPerSec/100);		}	    } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {		char d[4];		if ( input->readBlock(d,4) != 4 ) {		    return FALSE;		}		if ( qstrncmp(d,"WAVE",4) != 0 ) {		    // skip		    if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) {			return FALSE;		    }		}	    } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {		int cur_pos = input->at();		if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) {		    return FALSE;		}		swapChunkData(&chunkdata);		if ( chunkdata.formatTag == WAVE_FORMAT_GSM610 ) {		    // validate the GSM header details.		    if ( chunk.size < (sizeof(chunkdata) + 4) ) {			qDebug( "WAV file: BAD GSM HEADER SIZE" );			return FALSE;		    }		    if ( input->readBlock( (char *)&gsmext, sizeof(gsmext) ) != sizeof(gsmext) ) {			qDebug( "WAV file: TRUNCATED GSM HEADER" );			return FALSE;		    }		    swapGsmExtHeader(&gsmext);		    if ( gsmext.wExtSize != 2 ||		         gsmext.samplesPerBlock != 320 ||			 chunkdata.blockAlign != 65 ) {			qDebug( "WAV file: INCORRECT GSM PARAMETERS" );			return FALSE;		    }		} else if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {		    qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);		    return FALSE;		}		if ( chunk.size > 1000000000 || !input->at( cur_pos + chunk.size ) ) {		    return FALSE;		}	    } else {		// ignored chunk		if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) {		    return FALSE;		}	    }	} // while	// initialize the GSM decompression code.	if ( chunkdata.formatTag == WAVE_FORMAT_GSM610 ) {	    gsmhandle = gsm_create();	    if ( !gsmhandle ) {		return FALSE;	    }	    int value = 1;	    gsm_option( gsmhandle, GSM_OPT_WAV49, &value );	}	return TRUE;    }    // gets a sample from the file    bool getSample(int& l, int& r)    {	l = r = 0;	if ( input == 0 )	    return FALSE;	if ( (wavedata_remaining < 0) || !max )	    return FALSE;	if ( out >= max ) {	    max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) );	    wavedata_remaining -= max;	    out = 0;	    if ( max <= 0 ) {		max = 0;		return TRUE;	    }	}	if ( chunkdata.wBitsPerSample == 8 ) {	    l = (data[out++] - 128) * 128;	} else {#ifdef IS_BIG_ENDIAN	    l = swap16(((short*)data)[out/2]);#else	    l = ((short*)data)[out/2];#endif	    out += 2;	}	if ( chunkdata.channels == 1 ) {	    r = l;	} else {	    if ( chunkdata.wBitsPerSample == 8 ) {		r = (data[out++] - 128) * 128;	    } else {#ifdef IS_BIG_ENDIAN		r = swap16(((short*)data)[out/2]);#else		r = ((short*)data)[out/2];#endif		out += 2;	    }	}	return TRUE;    } // getSample    // get the next block of GSM data to be played    bool nextGsmBlock()    {	if ( input == 0 )	    return FALSE;	if ( (wavedata_remaining < 0) || !max )	    return FALSE;	if ( out >= max ) {	    // read as many 65-byte GSM frames as possible	    int size = QMIN(sound_buffer_size,wavedata_remaining);	    size -= size % 65;	    max = input->readBlock( (char*)data, (uint)size );	    wavedata_remaining -= max;	    out = 0;	    if ( max < 65 ) {		max = 0;		return FALSE;	    }	}	// decode the two halves of the 65-byte GSM frame	gsm_decode( gsmhandle, (gsm_byte *)(data + out), gsmsamples );	gsm_decode( gsmhandle, (gsm_byte *)(data + out + 33), gsmsamples + 160 );	out += 65;	gsmnext = 0;	return TRUE;    } // nextGsmBlock};WavPlugin::WavPlugin() {    d = new WavPluginData;    d->input = 0;}WavPlugin::~WavPlugin() {    close();    delete d;}bool WavPlugin::isFileSupported( const QString& path ) {    debugMsg( "WavPlugin::isFileSupported" );    char *ext = strrchr( path.latin1(), '.' );    // Test file extension    if ( ext ) {	if ( strncasecmp(ext, ".raw", 4) == 0 )	    return TRUE;	if ( strncasecmp(ext, ".wav", 4) == 0 )	    return TRUE;	if ( strncasecmp(ext, ".wave", 4) == 0 )	    return TRUE;    }    return FALSE;}bool WavPlugin::open( const QString& path ) {    debugMsg( "WavPlugin::open" );    d->max = d->out = sound_buffer_size;    d->wavedata_remaining = 0;    d->samples_due = 0;    d->input = new QFile( path );    if ( d->input->open(IO_ReadOnly) == FALSE ) {	qDebug("couldn't open file");	delete d->input;	d->input = 0;	return FALSE;    }    d->initialise();    return TRUE;}bool WavPlugin::close() {    debugMsg( "WavPlugin::close" );    if (d->input) {	d->input->close();    }    delete d->input;    d->input = 0;    return TRUE;}bool WavPlugin::isOpen() {    debugMsg( "WavPlugin::isOpen" );    return ( d->input != 0 );}int WavPlugin::audioStreams() {    debugMsg( "WavPlugin::audioStreams" );    return 1;}int WavPlugin::audioChannels( int ) {    debugMsg( "WavPlugin::audioChannels" );    return 2; // ### Always scale audio to stereo samples}int WavPlugin::audioFrequency( int ) {    debugMsg( "WavPlugin::audioFrequency" );    return 44100; // ### Always scale to frequency of 44100}int WavPlugin::audioSamples( int ) {    debugMsg( "WavPlugin::audioSamples" );    return d->samples;}bool WavPlugin::audioSetSample( long, int ) {    debugMsg( "WavPlugin::audioSetSample" );    return FALSE;}long WavPlugin::audioGetSample( int ) {    debugMsg( "WavPlugin::audioGetSample" );    return 0;}#ifdef OLD_MEDIAPLAYER_APIbool WavPlugin::audioReadSamples( short *, int, long, int ) {    debugMsg( "WavPlugin::audioReadSamples" );    return FALSE;}bool WavPlugin::audioReReadSamples( short *, int, long, int ) {    debugMsg( "WavPlugin::audioReReadSamples" );    return FALSE;}bool WavPlugin::audioReadMonoSamples( short *output, long samples, long& samplesMade, int ) {    debugMsg( "WavPlugin::audioReadMonoSamples" );    return !d->add( output, samples, samplesMade, FALSE );}bool WavPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {    debugMsg( "WavPlugin::audioReadStereoSamples" );    return !d->add( output, samples, samplesMade, TRUE );}#elsebool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) {    debugMsg( "WavPlugin::audioReadSamples" );    return d->add( output, samples, samplesMade, channels != 1 );}#endifdouble WavPlugin::getTime() {    debugMsg( "WavPlugin::getTime" );    return 0.0;}

⌨️ 快捷键说明

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