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

📄 beaudio.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/* * beaudio.cxx * * Sound driver implementation. * * Portable Windows Library * * Copyright (c) 1993-2001 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s):  * Yuri Kiryanov, ykiryanov at users.sourceforge.net, * Jac Goudsmit <jac@be.com>. * * $Log: beaudio.cxx,v $ * Revision 1.16  2004/10/26 18:08:54  ykiryanov * Added code for old Media Kit, to be backwards compatible with R5, and Zeta ifdef * * Revision 1.15  2004/06/16 01:55:10  ykiryanov * Added usage of lastReadCount - sound capture now works * * Revision 1.14  2004/05/30 04:48:45  ykiryanov * Stable version * * Revision 1.12  2004/05/14 05:26:57  ykiryanov * Fixed dynamic cast bug * * Revision 1.11  2004/04/18 00:32:26  ykiryanov * Fized compiler choking on <dynamic_cast>. * * Revision 1.10  2004/04/02 03:29:07  ykiryanov * New improved code * * Revision 1.9  2002/02/09 00:52:01  robertj * Slight adjustment to API and documentation for volume functions. * * Revision 1.8  2002/02/07 20:57:21  dereks * add SetVolume and GetVolume methods to PSoundChannelBeOS * * Revision 1.7  2001/07/09 06:16:15  yurik * Jac Goudsmit's BeOS changes of July,6th. Cleaning up media subsystem etc. * * Revision 1.6  2000/12/16 13:08:56  rogerh * BeOS changes from Yuri Kiryanov <openh323@kiryanov.com> * * Revision 1.5  2000/04/19 00:13:52  robertj * BeOS port changes. * * Revision 1.4  1999/09/21 00:56:29  robertj * Added more sound support for BeOS (thanks again Yuri!) * * Revision 1.3  1999/06/28 09:28:02  robertj * Portability issues, especially n BeOS (thanks Yuri!) * * Revision 1.2  1999/03/05 07:03:27  robertj * Some more BeOS port changes. * * Revision 1.1  1999/03/02 05:41:59  robertj * More BeOS changes * */#include <ptlib.h>#include <ptlib/unix/ptlib/beaudio.h>PCREATE_SOUND_PLUGIN(BeOS, PSoundChannelBeOS);/////////////// Debugging stuff ///////////////#define TL (7)#define PRINT(x) //do { printf(__FILE__ ":%d %s ", __LINE__, __FUNCTION__); printf x; printf("\n"); } while(0)#define STATUS(x) // PRINT((x "=%ld", (long)dwLastError))#define PRINTCB(x) // PRINT(x)//#define SOUNDDETECT 1 define this for printed output of first pb/rec audio//#define FILEDUMP 1 define this for dumping audio to wav file// Macros and global vars for debugging#ifdef SOUNDDETECT#define DETECTVARS(buffer,numframes) short *detbuf=(short*)buffer; size_t detframes=numframes;#define DETECTSOUND() \do { \	static bool silence=true; \	if (silence) \	{ \		for (size_t i=0; i<detframes; i++) \		{ \			if (detbuf[i]>=255) \			{ \				PRINT(("SOUND DETECTED at %p",detbuf)); \				for (size_t j=0; j<detframes && j<30; j++) \				{ \					char *x; \					asprintf(&x,"%%%ds\n",(detbuf[j]>>10)+32); \					printf(x,"."); \					free(x); \				} \				silence=false; \				break; \			} \		} \	} \} while(0)#else#define DETECTVARS(buffer,numframes)#define DETECTSOUND()#endif#ifdef FILEDUMP#include "beaudio/AudioFileWriter.h"BAudioFileWriter *playwriter=NULL;BAudioFileWriter *recwriter=NULL;#endif////////////////////////////////////////////////////////////////////////////////// PSoundPSound::PSound(unsigned channels,               unsigned samplesPerSecond,               unsigned bitsPerSample,               PINDEX   bufferSize,               const BYTE * buffer){	encoding = 0;	SetFormat(channels, samplesPerSecond, bitsPerSample);	if (buffer != NULL)	{		memcpy(GetPointer(bufferSize), buffer, bufferSize);	}}PSound::PSound(const PFilePath & filename){	encoding = 0;		// Set the default format	SetFormat(1, 8000, 16);		// The format is changed if the file is succesfully loaded.	Load(filename);}PSound & PSound::operator=(const PBYTEArray & data){	PBYTEArray::operator=(data);	return *this;}void PSound::SetFormat(unsigned channels,                       unsigned samplesPerSecond,                       unsigned bitsPerSample){	// NOTE: all constructors should call this to initialize	// the local members, especially formatInfo.	// Do NOT call the function with any parameter set to 0!	sampleSize=bitsPerSample;	sampleRate=samplesPerSecond;	numChannels = channels;	// We don't use the encoding member (although we could probably set it to 0=PCM)	// Let the application know it shouldn't assume anything	encoding = 1;		// The formatInfo member to us is a media_format structure.	BOOL setsize_formatInfo=formatInfo.SetSize(sizeof(media_format));	PAssert(setsize_formatInfo, "Unable to set size for sound info array");		// Initialize the media_format struct	// The numbers of bits that we support here are 8, 16 or 32 bits (signed),	// results for other sizes are not defined.	media_format &format=*(media_format*)(const BYTE *)formatInfo;	format.type = B_MEDIA_RAW_AUDIO;	format.u.raw_audio = media_raw_audio_format::wildcard;	format.u.raw_audio.frame_rate=(float)sampleRate;	format.u.raw_audio.channel_count=numChannels;	format.u.raw_audio.format=(sampleSize / 8) & 0xF; 	format.u.raw_audio.byte_order=B_MEDIA_HOST_ENDIAN;	format.u.raw_audio.buffer_size=(channels * samplesPerSecond * (bitsPerSample/8))/10; // 1/10 sec buffer}BOOL PSound::Load(const PFilePath & filename){	// format is a reference to the formatInfo member which stores info	// about the media format. This is needed for writing the data back	// or for playing the sound.	media_format 	   &format=*(media_format *)(const BYTE *)formatInfo;	// Create BEntry from file name	BEntry entry(filename, true);	if ((dwLastError=entry.InitCheck())!=B_OK)	{		STATUS("entry.InitCheck()");		return FALSE;	}	// Create entry_ref from BEntry		entry_ref ref;	if ((dwLastError=entry.GetRef(&ref))!=B_OK)	{		STATUS("entry.GetRef()");		return FALSE;	}	// Create BMediaFile for read access from the entry_ref	BMediaFile file(&ref);	if ((dwLastError=file.InitCheck())!=B_OK)	{		STATUS("file.InitCheck()");		return FALSE;	}		// Search for the first media track that can be decoded	BMediaTrack *ptrack = NULL;	for (int index=0; (index<file.CountTracks()) && (dwLastError==B_OK); index++)	{		ptrack = file.TrackAt(index);		if (ptrack)		{			dwLastError = ptrack->InitCheck();		}		else		{			dwLastError = B_ERROR; //todo: change error code		}		if (dwLastError==B_OK)		{			// Get media format; we're looking for a raw audio track.			format.type = B_MEDIA_RAW_AUDIO;			format.u.raw_audio = media_raw_audio_format::wildcard;			dwLastError = ptrack->DecodedFormat(&format);					if ((dwLastError==B_OK) && (format.type==B_MEDIA_RAW_AUDIO))			{				break; // found a decodable track			}		}		else		{			STATUS("TrackAt() failed, error");		}				// if we found a track and arrived at this point, the track we found		// was not decodable		if (ptrack)		{			dwLastError=file.ReleaseTrack(ptrack); // destroys ptrack		}	}		// if an error occurred during track scanning, leave now	if (dwLastError!=B_OK)	{		return FALSE;	}	// Get a reference to the raw output format	media_raw_audio_format &rawformat = format.u.raw_audio;	// Fill in our fields from the format			sampleSize    = (rawformat.format & 0xF) * 8;	numChannels   = rawformat.channel_count;	if (rawformat.frame_rate>0.0 && rawformat.frame_rate<=(float)0xFFFFFFFFU)	{		sampleRate = (unsigned)(rawformat.frame_rate);	}	else	{		// unknown or unrepresentable sample rate.		// It's not really documented what we should do in this case but		// it probably doesn't matter either... 		sampleRate = 0; 	}		// Get the number of frames for the track and determine how much	// memory we need to store the file's data	// The multiplication might overflow for huge files but we don't	// want to read them into memory anyway so I guess it's ok...	int64 numframes = ptrack->CountFrames();	int64 framesize = numChannels * (sampleSize/8);	int64 numbytes  = numframes * framesize;		// Set the size of the object's data area	if (!SetSize(numbytes))	{		PRINT(("Can't set size of sound to %Ld", numbytes));		dwLastError = B_ERROR; //todo replace by better error code		return FALSE; // BMediaFile will destroy ptrack	}		// Read all frames into memory. NOTE: not thread safe!	BYTE* dest = GetPointer();		// destination pointer	int64 framecount = numframes;	// number of frames left to read	int64 framesread;				// number of actual frames done	while ((framecount!=0) && (dwLastError==B_OK))	{		framesread = framecount;		dwLastError = ptrack->ReadFrames(dest, &framesread);		dest += framesread * framesize;		framecount -= framesread;	}		// return true for success	return (dwLastError==B_OK); // BMediaFile will destroy ptrack}BOOL PSound::Save(const PFilePath & filename){	// format is a reference to the formatInfo member which stores info	// about the media format. This is needed for writing the data back	// or for playing the sound.	media_format 	   &format=*(media_format *)(const BYTE *)formatInfo;	// Get the file type from the file name's extension; if none, use wav	PFilePathString filetype=filename.GetType(); // e.g. ".wav"	if (filetype=="")	{		filetype="wav";	}	else	{		filetype=filetype.Mid(1); // cut off the '.'	}		// Try to find the file format in BeOS's list of formats	media_file_format mfi;	int32 cookie=0;	while ((dwLastError=get_next_file_format(&cookie, &mfi))==B_OK)	{		if (!strcasecmp(mfi.file_extension, (const char *)filetype))		{			break;		}	}	if (dwLastError!=B_OK)	{		// didn't find file format		PRINT(("Couldn't find media_file_format for \"%s\"", (const char *)filetype));		return FALSE;	}		// Create BEntry from file name	BEntry	entry(filename, true);	if ((dwLastError=entry.InitCheck())!=B_OK)	{		STATUS("entry.InitCheck()");		return FALSE;	}		// Create entry_ref from BEntry		entry_ref ref;	if ((dwLastError=entry.GetRef(&ref))!=B_OK)	{		STATUS("entry.GetRef()");		return FALSE;	}	// Create BMediaFile for write access from the entry_ref	BMediaFile file(&ref, &mfi, B_MEDIA_FILE_REPLACE_MODE);	if ((dwLastError=file.InitCheck())!=B_OK)	{		STATUS("file.InitCheck()");		return FALSE;	}		// Find an encoder. The input format is the format we have stored in	// our formatInfo member.	cookie=0;	media_format outformat;	media_codec_info mci,validmci,rawmci, *pmci;	bool found_encoder = false;	bool found_raw_encoder = false;	while (get_next_encoder(&cookie, &mfi, &format, &outformat, &mci)==B_OK)	{		found_encoder=true;				if (outformat.type==B_MEDIA_RAW_AUDIO)		{			rawmci=mci;			found_raw_encoder=true;		}		else		{			validmci=mci;		}	}		// Choose an encoder:	// If a raw-output encoder was found, use it.	// Else, use the last found encoded-output encoder, if any.	// This method of choosing will make sure that most file formats 	// will get the most common encoding (PCM) whereas it's still possible	// to choose another output format like MP3, if so dictated by the	// file format.	// BeOS is smart enough not to return an encoder that produces raw audio	// for e.g. the MP3 file format, but it knows that there are many ways	// to encode e.g. a WAV file and we don't want to put anything	// unexpected into a WAV file, do we?	BMediaTrack	*ptrack = NULL;	if (found_encoder)	{		if (found_raw_encoder)		{			PRINT(("Using raw encoder"));			pmci=&rawmci;		}		else		{			// don't use mci instead of validmci,			// it could be unreliable after the last call to get_next_encoder			PRINT(("Using non-raw encoder"));			pmci=&validmci;		}				// Create a BMediaTrack in the file using the selected encoder		ptrack = file.CreateTrack(&format, pmci);		if (ptrack)		{			dwLastError = ptrack->InitCheck();		}		else		{			dwLastError = B_ERROR; //todo: change error code		}	}	else	{		dwLastError=B_ERROR; //todo: change error code	}	if (dwLastError!=B_OK)	{		STATUS("Encoder not found or file.CreateTrack() error");		return FALSE; // BMediaFile will destroy ptrack	}		// We're only creating one track so commit the header now	if ((dwLastError = file.CommitHeader())!=B_OK)	{		STATUS("file.CommitHeader()");		return FALSE;	}		// Determine how many frames we have to write	// There is a small possibility of a divide by zero but this only	// happens if the object is not properly initialized.	PINDEX numbytes = GetSize();	int32 framesize = numChannels * (sampleSize/8);	int32 numframes = numbytes / framesize; // divide by zero possibility ignored.			if ((dwLastError=ptrack->WriteFrames((const BYTE *)*this, numframes))!=B_OK)	{		STATUS("ptrack->WriteFrames()");		return FALSE; // BMediaFile will destroy ptrack	}		return (file.CloseFile()==B_OK); // BMediaFile will destroy ptrack}BOOL PSound::Play(){	PSoundChannelBeOS player(PSoundChannelBeOS::GetDefaultDevice(PSoundChannelBeOS::Player), PSoundChannelBeOS::Player, numChannels, sampleRate, sampleSize);		if (!player.IsOpen())	{		PRINT(("PSoundChannelBeOS constructor failed to open"));		return FALSE;	}		return player.PlaySound(*this, TRUE);}

⌨️ 快捷键说明

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