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

📄 audiofile.cpp

📁 GNU ccAudio2 is a stand-alone portable C++ class framework for manipulating audio data. It has exist
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.//  // 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.// // As a special exception, you may use this file as part of a free software// library without restriction.  Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License.  This exception does not however// invalidate any other reasons why the executable file might be covered by// the GNU General Public License.//// This exception applies only to the code released under the name GNU// ccAudio.  If you copy code from other releases into a copy of GNU// ccAudio, as the General Public License permits, the exception does// not apply to the code that you add in this way.  To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU ccAudio, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include "private.h"#include "audio2.h"#include <cstdio>using namespace ost;static const char * const ErrorStrs[] = {	"errSuccess",	"errReadLast",	"errNotOpened",	"errEndOfFile",	"errStartOfFile",	"errRateInvalid",	"errEncodingInvalid",	"errReadInterrupt",	"errWriteInterrupt",	"errReadFailure",	"errWriteFailure",	"errReadIncomplete",	"errWriteIncomplete",	"errRequestInvalid",	"errTOCFailed",	"errStatFailed",	"errInvalidTrack",	"errPlaybackFailed",	"errNotPlaying"};AudioCodec *AudioFile::getCodec(void){	Encoding e = getEncoding();	switch(e)	{	case alawAudio:		return AudioCodec::getCodec(e, "g.711");	case mulawAudio:		return AudioCodec::getCodec(e, "g.711");	case g721ADPCM:	case okiADPCM:	case voxADPCM:		return AudioCodec::getCodec(e, "g.721");	case g722_7bit:	case g722_6bit:		return AudioCodec::getCodec(e, "g.722");	case g723_3bit:	case g723_5bit:		return AudioCodec::getCodec(e, "g.723");	default:		return NULL;	}}void AudioFile::setShort(unsigned char *data, unsigned short val){	if(info.order == __BIG_ENDIAN)	{		data[0] = val / 256;		data[1] = val % 256;	}	else	{		data[1] = val / 256;		data[0] = val % 256;	}}unsigned short AudioFile::getShort(unsigned char *data){	if(info.order == __BIG_ENDIAN)		return data[0] * 256 + data[1];	else		return data[1] * 256 + data[0];}void AudioFile::setLong(unsigned char *data, unsigned long val){	int i = 4;	while(i-- > 0)	{		if(info.order == __BIG_ENDIAN)			data[i] = (unsigned char)(val & 0xff);		else			data[3 - i] = (unsigned char)(val & 0xff);		val /= 256;	}}unsigned long AudioFile::getLong(unsigned char * data){	int i = 4;	unsigned long val =0;	while(i-- > 0)	{		if(info.order == __BIG_ENDIAN)			val = (val << 8) | data[3 - i];		else			val = (val << 8) | data[i];	}	return val;}AudioFile::AudioFile(const char *name, unsigned long sample) :AudioBase(){	pathname = NULL;	initialize();	AudioFile::open(name);	if(!isOpen())		return;	setPosition(sample);}AudioFile::AudioFile(const char *name, Info *inf, unsigned long samples) :AudioBase(inf){	pathname = NULL;	initialize();	AudioFile::create(name, inf);	if(!isOpen())		return;	setMinimum(samples);}AudioFile::~AudioFile(){	AudioFile::close();	AudioFile::clear();}void AudioFile::create(const char *name, Info *myinfo, bool exclusive, timeout_t framing){	int pcm = 0;	unsigned char aufile[24];	unsigned char riffhdr[40];	const char *ext = strrchr(name, '/');	if(!ext)		ext = strrchr(name, '\\');	if(!ext)		ext = strrchr(name, ':');	if(!ext)		ext = strrchr(name, '.');	else		ext = strrchr(ext, '.');	if(!ext)		ext = ".none";	mode = modeWrite;		if(!afCreate(name, exclusive))		return;	memset(riffhdr, 0, sizeof(riffhdr));	memcpy(&info, myinfo, sizeof(info));	info.annotation = NULL;	pathname = new char[strlen(name) + 1];	strcpy(pathname, name);	if(myinfo->annotation)	{		info.annotation = new char[strlen(myinfo->annotation) + 1];		strcpy(info.annotation, myinfo->annotation);	}	if(!stricmp(ext, ".raw") || !stricmp(ext, ".bin"))	{		info.format = raw;		if(info.encoding == unknownEncoding)			info.encoding = pcm16Mono;	}	else if(!stricmp(ext, ".au") || !stricmp(ext, ".snd"))	{		info.order = 0;		info.format = snd;	}	else if(!stricmp(ext, ".wav") || !stricmp(ext, ".wave"))	{		info.order = 0;		info.format = wave;	}	else if(!stricmp(ext, ".ul") || !stricmp(ext, ".ulaw") || !stricmp(ext, ".mulaw"))	{		info.encoding = mulawAudio;		info.format = raw;		info.order = 0;		info.rate = 8000;	}	else if(!stricmp(ext, ".al") || !stricmp(ext, ".alaw"))	{		info.encoding = alawAudio;		info.format = raw;		info.order = 0;		info.rate = 8000;	}	else if(!stricmp(ext, ".sw") || !stricmp(ext, ".pcm"))	{		info.encoding = pcm16Mono;		info.format = raw;		info.order = 0;	}	else if(!stricmp(ext, ".vox"))	{		info.encoding = voxADPCM;		info.format = raw;		info.order = 0;		info.rate = 6000;	}	else if(!stricmp(ext, ".gsm"))	{		info.encoding = gsmVoice;		info.format = raw;		info.order = 0;		info.rate = 8000;		info.framecount = 160;		info.framesize = 33;		info.bitrate = 13200;	}	else if(!stricmp(ext, ".adpcm"))	{		info.encoding = g721ADPCM;		info.format = raw;		info.order = 0;		info.rate = 8000;	}	else if(!stricmp(ext, ".a24"))	{		info.encoding = g723_3bit;		info.format = raw;		info.order = 0;		info.rate = 8000;	}	else if(!stricmp(ext, ".sx"))	{		info.encoding = sx96Voice;		info.format = raw;		info.order = 0;		info.rate = 8000;	}	else if(!stricmp(ext, ".a40"))	{		info.encoding = g723_5bit;		info.format = raw;		info.order = 0;		info.rate = 8000;	}	else if(!stricmp(ext, ".cda"))	{		info.encoding = cdaStereo;		info.format = raw;		info.order = __LITTLE_ENDIAN;		info.rate = 44100;	}	switch(info.format)	{	case wave:	case riff:		/*		 * RIFF header		 *		 * 12 bytes		 *		 * 0-3: RIFF magic "RIFF" (0x52 49 46 46)		 *		 * 4-7: RIFF header chunk size		 *      (4 + (8 + subchunk 1 size) + (8 + subchunk 2 size))		 *		 * 8-11: WAVE RIFF type magic "WAVE" (0x57 41 56 45)		 */		if(!info.order)			info.order = __LITTLE_ENDIAN;		if(info.order == __LITTLE_ENDIAN)			strncpy((char *)riffhdr, "RIFF", 4);		else			strncpy((char *)riffhdr, "RIFX", 4);		if(!info.rate)			info.rate = Audio::getRate(info.encoding);		if(!info.rate)			info.rate = rate8khz;		header = 0;		memset(riffhdr + 4, 0xff, 4);		strncpy((char *)riffhdr + 8, "WAVE", 4);		if(afWrite(riffhdr, 12) != 12)		{			AudioFile::close();			return;		}		/*		 * Subchunk 1: WAVE metadata		 *		 * Length: 24+		 *		 * (offset from start of subchunk 1) startoffset-endoffset		 *		 * (0) 12-15: WAVE metadata magic "fmt " (0x 66 6d 74 20)		 *		 * (4) 16-19: subchunk 1 size minus 8.  0x10 for PCM.		 *		 * (8) 20-21: Audio format code.  0x01 for linear PCM.		 * More codes here:		 * http://www.goice.co.jp/member/mo/formats/wav.html		 *		 * (10) 22-23: Number of channels.  Mono = 0x01,		 * Stereo = 0x02.		 *		 * (12) 24-27: Sample rate in samples per second. (8000, 		 * 44100, etc)		 *		 * (16) 28-31: Bytes per second = SampleRate *		 * NumChannels * (BitsPerSample / 8)		 *		 * (20) 32-33: Block align (the number of bytes for		 * one multi-channel sample) = Numchannels *		 * (BitsPerSample / 8)		 *		 * (22) 34-35: Bits per single-channel sample.  8 bits		 * per channel sample = 0x8, 16 bits per channel		 * sample = 0x10		 *		 * (24) 36-37: Size of extra PCM parameters for		 * non-PCM formats.  If a PCM format code is		 * specified, this doesn't exist.		 *		 * Subchunk 3: Optional 'fact' subchunk for non-PCM formats		 * (26) 38-41: WAVE metadata magic 'fact' (0x 66 61 63 74)		 * 		 * (30) 42-45: Length of 'fact' subchunk, not		 * including this field and the fact		 * identification field (usually 4)		 *		 * (34) 46-49: ??? sndrec32.exe outputs 0x 00 00 00 00		 * here.  See 		 * http://www.health.uottawa.ca/biomech/csb/ARCHIVES/riff-for.txt		 *		 */		memset(riffhdr, 0, sizeof(riffhdr));		strncpy((char *)riffhdr, "fmt ", 4);		// FIXME A bunch of the following only works for PCM		// and mulaw/alaw, so you'll probably have to fix it		// if you want to use one of the other formats.		if(info.encoding < cdaStereo)			setLong(riffhdr + 4, 18);		else			setLong(riffhdr + 4, 16);		setShort(riffhdr + 8, 0x01); // default in case invalid encoding specified		if(isMono(info.encoding))			setShort(riffhdr + 10, 1);		else			setShort(riffhdr + 10, 2);		setLong(riffhdr + 12, info.rate);		setLong(riffhdr + 16, (unsigned long)toBytes(info, info.rate));		setShort(riffhdr + 20, (snd16_t)toBytes(info, 1));		setShort(riffhdr + 22, 0);		switch(info.encoding)		{		case pcm8Mono:		case pcm8Stereo:			setShort(riffhdr + 22, 8);			pcm = 1;			break;		case pcm16Mono:		case pcm16Stereo:		case cdaMono:		case cdaStereo:			setShort(riffhdr + 22, 16);			pcm = 1;			break;		case pcm32Mono:		case pcm32Stereo:			setShort(riffhdr + 22, 32);			pcm = 1;			break;		case alawAudio:			setShort(riffhdr + 8, 6);			setShort(riffhdr + 22, 8);			break;		case mulawAudio:			setShort(riffhdr + 8, 7);			setShort(riffhdr + 22, 8);			break;			// FIXME I'm pretty sure these are supposed to			// be writing to offset 22 instead of 24...		case okiADPCM:			setShort(riffhdr + 8, 0x10);			setShort(riffhdr + 24, 4);			break;		case voxADPCM:			setShort(riffhdr + 8, 0x17);			setShort(riffhdr + 24, 4);			break;		case g721ADPCM:			setShort(riffhdr + 8, 0x40);			setShort(riffhdr + 24, 4);			break;		case g722Audio:			setShort(riffhdr + 8, 0x64);			setShort(riffhdr + 24, 8);			break;		case gsmVoice:		case msgsmVoice:			setShort(riffhdr + 8, 0x31);			setShort(riffhdr + 24, 260);			break;		case g723_3bit:			setShort(riffhdr + 8, 0x14);			setShort(riffhdr + 24, 3);			break;		case g723_5bit:			setShort(riffhdr + 8, 0x14);			setShort(riffhdr + 24, 5);		case unknownEncoding:		default:			break;		}		if(pcm == 0) {			setShort(riffhdr + 24, 0);			strncpy((char *)(riffhdr + 26), "fact", 4);			setLong(riffhdr + 30, 4);			setLong(riffhdr + 34, 0);			if(afWrite(riffhdr, 38) != 38)			{				AudioFile::close();				return;			}		}		else {			if(afWrite(riffhdr, 24) != 24)			{				AudioFile::close();				return;			}		}				/* 		 * Subchunk 2: data subchunk		 *		 * Length: 8+		 *		 * (0) 36-39: data subchunk magic "data" (0x 64 61 74 61)		 *		 * (4) 40-43: subchunk 2 size = 		 * NumSamples * NumChannels * (BitsPerSample / 8)		 * Note that this does not include the size of this		 * field and the previous one.		 *		 * (8) 44+: Samples		 */		memset(riffhdr, 0, sizeof(riffhdr));		strncpy((char *)riffhdr, "data", 4);		memset(riffhdr + 4, 0xff, 4);		if(afWrite(riffhdr, 8) != 8)		{			AudioFile::close();			return;		}				header = getAbsolutePosition();		length = getAbsolutePosition();		break;	case snd://		if(!info.order)			info.order = __BIG_ENDIAN;		if(!info.rate)			info.rate = Audio::getRate(info.encoding);		if(!info.rate)			info.rate = rate8khz;		strncpy((char *)aufile, ".snd", 4);		if(info.annotation)			setLong(aufile + 4, 24 + (unsigned long)strlen(info.annotation) + 1);		else			setLong(aufile + 4, 24);		header = getLong(aufile + 4);		setLong(aufile + 8, ~0l);		switch(info.encoding)		{		case pcm8Stereo:		case pcm8Mono:			setLong(aufile + 12, 2);			break;		case pcm16Stereo:		case pcm16Mono:		case cdaStereo:		case cdaMono:			setLong(aufile + 12, 3);			break;		case pcm32Stereo:		case pcm32Mono:			setLong(aufile + 12, 5);			break;		case g721ADPCM:			setLong(aufile + 12, 23);			break;		case g722Audio:		case g722_7bit:		case g722_6bit:			setLong(aufile + 12, 24);			break;		case g723_3bit:			setLong(aufile + 12, 25);			break;		case g723_5bit:			setLong(aufile + 12, 26);			break;		case alawAudio:			setLong(aufile + 12, 27);			break;		default:			setLong(aufile + 12, 1);		}		setLong(aufile + 16, info.rate);		if(isMono(info.encoding))			setLong(aufile + 20, 1);		else			setLong(aufile + 20, 2);		if(afWrite(aufile, 24) != 24)		{			AudioFile::close();			return;		}		if(info.annotation)			afWrite((unsigned char *)info.annotation, (unsigned long)strlen(info.annotation) + 1);		header = getAbsolutePosition();		length = getAbsolutePosition();		break;	case mpeg:		framing = 0;		info.headersize = 4;	// no crc...	case raw:		break;	}	if(framing)		info.setFraming(framing);	else			info.set();}void AudioFile::getWaveFormat(int request){	unsigned char filehdr[24];	int bitsize;	int channels;	if(request > 24)		request = 24;	if(!afPeek(filehdr, request))	{		AudioFile::close();		return;	}	channels = getShort(filehdr + 2);	info.rate = getLong(filehdr + 4);	switch(getShort(filehdr))	{	case 1:		bitsize = getShort(filehdr + 14);		switch(bitsize)		{		case 8:			if(channels > 1)				info.encoding = pcm8Stereo;			else				info.encoding = pcm8Mono;			break;		case 16:			if(info.rate == 44100)			{				if(channels > 1)					info.encoding = cdaStereo;				else					info.encoding = cdaMono;				break;			}			if(channels > 1)					info.encoding = pcm16Stereo;			else				info.encoding = pcm16Mono;			break;		case 32:			if(channels > 1)				info.encoding = pcm32Stereo;			else				info.encoding = pcm32Mono;			break;		default:			info.encoding = unknownEncoding;		}		break;	case 6:		info.encoding = alawAudio;		break;	case 7:		info.encoding = mulawAudio;		break;	case 0x10:		info.encoding = okiADPCM;		break;	case 0x17:		info.encoding = voxADPCM;		break;	case 0x40:		info.encoding = g721ADPCM;		break;	case 0x65:		info.encoding = g722Audio;		break;	case 0x31:		info.encoding = msgsmVoice;		break;	case 0x14:		bitsize = getLong(filehdr + 8) * 8 / info.rate;		if(bitsize == 3)			info.encoding = g723_3bit;		else			info.encoding = g723_5bit;		break;	default:		info.encoding = unknownEncoding;	}}void AudioFile::open(const char *name, Mode m, timeout_t framing){	unsigned char filehdr[24];	unsigned int count;	char *ext;	unsigned channels;	mpeg_audio *mp3 = (mpeg_audio *)&filehdr;		mode = m;	while(!afOpen(name, m))	{		if(mode == modeReadAny || mode == modeReadOne)			name = getContinuation();		else			name = NULL;		if(!name)			return;	}	pathname = new char[strlen(name) + 1];	strcpy(pathname, name);	header = 0l;	info.framesize = 0;	info.framecount = 0;	info.encoding = mulawAudio;	info.format = raw;	info.order = 0;	ext = strrchr(pathname, '.');	if(!ext)		goto done;	if(!stricmp(ext, ".ul") || !stricmp(ext, ".ulaw") || !stricmp(ext, ".mulaw"))	{		info.encoding = mulawAudio;		goto done;	}	if(!stricmp(ext, ".al") || !stricmp(ext, ".alaw"))	{		info.encoding = alawAudio;		goto done;	}	if(!stricmp(ext, ".sw") || !stricmp(ext, ".raw") || !stricmp(ext, ".pcm"))	{		info.encoding = pcm16Mono;		goto done;	}	if(!stricmp(ext, ".vox"))	{		info.encoding = voxADPCM;		goto done;	}	if(!stricmp(ext, ".adpcm"))	{		info.encoding = g721ADPCM;		goto done;	}	if(!stricmp(ext, ".a24"))	{		info.encoding = g723_3bit;		goto done;	}	if(!stricmp(ext, ".a40"))	{		info.encoding = g723_5bit;		goto done;	}	if(!stricmp(ext, ".cda"))	{		info.order = __LITTLE_ENDIAN;		info.encoding = cdaStereo;		goto done;	}	strcpy((char *)filehdr, ".xxx");	if(!afPeek(filehdr, 24))	{		AudioFile::close();		return;	}	if(!strncmp((char *)filehdr, "RIFF", 4))	{		info.format = riff;		info.order = __LITTLE_ENDIAN;	}	if(!strncmp((char *)filehdr, "RIFX", 4))	{		info.order = __BIG_ENDIAN;		info.format = riff;	}	if(!strncmp((char *)filehdr + 8, "WAVE", 4) && info.format == riff)	{		header = 12;		for(;;)		{			if(!afSeek(header))			{				AudioFile::close();				return;			}			if(!afPeek(filehdr, 8))			{				AudioFile::close();				return;			}			header += 8;			if(!strncmp((char *)filehdr, "data", 4))				break;			count = getLong(filehdr + 4);			header += count;			if(!strncmp((char *)filehdr, "fmt ", 4))				getWaveFormat(count);		}		afSeek(header);		goto done;	}	if(!strncmp((char *)filehdr, ".snd", 4))	{

⌨️ 快捷键说明

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