Welcome! Log In Create A New Profile

Advanced

Playing ogg and wav at the same time

Posted by elconde202 
Playing ogg and wav at the same time
July 11, 2011 07:49PM
Hi, I need to use asndlib (oggplayer.h) and aesndlib (wavplayer.h) but both can not be used at the same time. Is any way to play a sound with both? (Sorry for my bad english but i?m spanish)



Edited 1 time(s). Last edit at 07/11/2011 07:51PM by elconde202.
Re: Playing ogg and wav at the same time
July 11, 2011 09:51PM
I don't know the way, but why don't convert everything to ogg?

¿No sé la forma de hacerlo, pero porqué no lo conviertes todo a ogg?
Re: Playing ogg and wav at the same time
July 12, 2011 09:10AM
Here's something that may help, it's in c++
This loads up oggs and wavs.
It should be part of Game Framework but the package is a bit out of date (no sound) so I've provided an updated sound manager part here - let me know if you need some example calling code and I'll update the framework to include the sound and a working example or both ogg & wav rather than slapping large amounts of code here.


ADDED NOTE: SAVING THIS AS HTML HAS BROKEN THE CODE, greater than & less than do not show.
I'll post again once I've added it somewhere it can be viewed.

SoundManager.h
#ifndef SoundManager_H_
#define SoundManager_H_

#include 
#include 
#include 
#include 
#include "HashLabel.h"

class RawSample
{
public:
	int Play(u8 VolumeLeft=0xff, u8 VolumeRight=0xff, bool bLoop = false);
	void SetRawData(u8* pData) {m_RawData = pData;}
	void SetRawDataLength(u32 Data) {m_RawDataLength = Data;}
	void SetNumberOfChannels(u8 Data) {m_NumberOfChannels = Data;}
	void SetSampleRate(u32 Data) {m_SampleRate = Data;}
	void SetBitsPerSample(u32 Data) { m_BitsPerSample = Data; }

private:
	u8* m_RawData;
	u32	m_RawDataLength;
	u8  m_NumberOfChannels; // uses SND_SetVoice format as defined in 'asndlib.h'
	u32 m_SampleRate;		// pitch frequency (in Hz)
	u32 m_BitsPerSample ;	// 8bits 16 bits
};


class SoundManager
{
public:

	SoundManager();
	~SoundManager();
		
	void LoadSound( std::string FullFileNameWithPath, std::string LookUpName );  // wav, ogg

	std::map m_SoundContainer;
	RawSample* GetSound(HashLabel SoundName) { return m_SoundContainer[SoundName]; }
	int PlaySound(HashLabel SoundName,u8 VolumeLeft = 255, u8 VolumeRight = 255, bool bLoop = false);
	void StopSound(u8 Chan);

	

private:

	void StoreSoundFromOgg(std::string FullFileNameWithPath,std::string LookUpName);
	void StoreSoundFromWav( std::string FullFileNameWithPath, std::string LookUpName );

	void Init();
	void UnInit();

	//A WAV header consits of several chunks:
	struct RIFFChunk
	{
		char RIFF[4];		// "RIFF"  - big-endian form
		u32 NextChunkSize;	// 36 + SubChunk2Size, or more precisely:
                            //  4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
                            // This is the size of the rest of the chunk 
                            // following this number.  This is the size of the 
                            // entire file in bytes minus 8 bytes for the
                            // two fields not included in this count:
                            // ChunkID and ChunkSize.
		char RIFFType[4];	// Contains the letters "WAVE"  - big-endian form
	};

	struct fmtChunk
	{
		char  fmt[4];		// "fmt "  - big-endian form
		u32  fmtLength;		// 16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
		u16 WaveType;		//PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
		
		//format 
		//#define  VOICE_MONO_16BIT   1 
		//#define  VOICE_MONO_8BIT   0 
		//#define  VOICE_STEREO_16BIT   3 
		//#define  VOICE_STEREO_8BIT   2 
		//
		u16 Channels;		//Mono 1, Stereo 2

		u32 SampleRate;		//8000, 44100, etc.
		u32 BytesPerSecond; // == SampleRate * NumChannels * BitsPerSample/8
		u16 BlockAlignment; // == NumChannels * BitsPerSample/8   The number of bytes for one sample including
                            // all channels. I wonder what happens when this number isn't an integer?
		u16 BitResolution;  // bits Per Sample 8 bits, 16 bits
	};

	struct dataChunk
	{
		char data[4];    // "data"  -  big-endian form
		u32 dataLength;  // sound data length
	};


};


#endif

SoundManager.cpp
#include 

#include "SoundManager.h"
#include "malloc.h"
#include "debug.h"
#include "string.h"
#include "config.h"
#include "WiiManager.h"
#include "WiiFile.h"
#include "Util.h"
#include "tremor/ivorbiscodec.h"
#include "tremor/ivorbisfile.h"

int RawSample::Play(u8 VolumeLeft, u8 VolumeRight, bool bLoop)
{
	if ( !Singleton::GetInstanceByRef().IsGameStateShowingGame() )
		return 0;

	int Chan = ASND_GetFirstUnusedVoice();

	if (bLoop)
		ASND_SetInfiniteVoice( Chan, m_NumberOfChannels,m_SampleRate,0, m_RawData, m_RawDataLength , VolumeLeft, VolumeRight);
	else
		ASND_SetVoice( Chan, m_NumberOfChannels,m_SampleRate,0, m_RawData, m_RawDataLength , VolumeLeft, VolumeRight, NULL);

	return Chan;
}	

int SoundManager::PlaySound(HashLabel SoundName, u8 VolumeLeft, u8 VolumeRight, bool bLoop)
{
	if ( !Singleton::GetInstanceByRef().IsGameStateShowingGame() )
		return 0;


	//todo - replace [] will something that will fail rather then create a new item we are looking for !
	RawSample* pRaw = GetSound(SoundName);
	if (pRaw!=NULL)
	{
		return m_SoundContainer[SoundName]->Play( VolumeLeft, VolumeRight, bLoop ); 
	}


	return -1;
}

void SoundManager::StopSound(u8 Chan)
{
	if ( !Singleton::GetInstanceByRef().IsGameStateShowingGame() )
		return;

	ASND_StopVoice(Chan);
}


SoundManager::SoundManager( )
{ 
	Init();
}

SoundManager::~SoundManager( )
{ 
	UnInit();
}

void SoundManager::Init( )
{ 
#ifdef ENABLE_SOUND
	SND_Init(INIT_RATE_48000);  // note: SND_xxx is the same as ASND_xxx
	SND_Pause(0);  
#endif
}

void SoundManager::UnInit( )
{ 
	ASND_Pause(1);  //pause
	ASND_End();
}
void SoundManager::LoadSound( std::string FullFileNameWithPath,std::string LookUpName )
{
	Util::StringToLower(FullFileNameWithPath);

	if (WiiFile::GetFileExtension(FullFileNameWithPath) == "wav")
	{
		StoreSoundFromWav(FullFileNameWithPath,LookUpName);
	}
	else if (WiiFile::GetFileExtension(FullFileNameWithPath) == "ogg")
	{
		StoreSoundFromOgg(FullFileNameWithPath,LookUpName);
	}
}

// StoreSoundFromWav is a supporting function for LoadSound
void SoundManager::StoreSoundFromWav( std::string FullFileNameWithPath,std::string LookUpName )
{
	FILE* WAVFile = WiiFile::FileOpenForRead((FullFileNameWithPath).c_str());
	//-------------------------------------------------------------
	// "RIFF" chunk discriptor
	RIFFChunk RIFFChunkData;
	fread(&RIFFChunkData, sizeof(RIFFChunk), 1, WAVFile);
	if ( strncmp ( RIFFChunkData.RIFF, "RIFF", 4 ) != 0 )
		ExitPrintf("'RIFF' check failed %c%c%c%c" ,RIFFChunkData.RIFF[0],RIFFChunkData.RIFF[1],RIFFChunkData.RIFF[2],RIFFChunkData.RIFF[3] );
	if ( strncmp ( RIFFChunkData.RIFFType, "WAVE", 4 ) != 0 )
		ExitPrintf("'WAVE' check failed %c%c%c%c",RIFFChunkData.RIFFType[0],RIFFChunkData.RIFFType[1],RIFFChunkData.RIFFType[2],RIFFChunkData.RIFFType[3]);
	//-------------------------------------------------------------
	// "fmt" sub-chunk
	fmtChunk fmtChunkData;
	fread(&fmtChunkData, sizeof(fmtChunk), 1, WAVFile);
	if ( strncmp ( fmtChunkData.fmt, "fmt ", 4 ) != 0 )
		ExitPrintf("fmt' check failed %c%c%c%c" , fmtChunkData.fmt[0],fmtChunkData.fmt[1],fmtChunkData.fmt[2],fmtChunkData.fmt[3]);

	fmtChunkData.Channels = Util::ENDIAN16(fmtChunkData.Channels);
	fmtChunkData.SampleRate = Util::ENDIAN32(fmtChunkData.SampleRate);
	//-------------------------------------------------------------
	// "data" sub-chunk
	dataChunk dataChunkData;
	fread(&dataChunkData, sizeof(dataChunk), 1, WAVFile);
	if ( strncmp ( dataChunkData.data, "data", 4 ) != 0 )
		ExitPrintf("'data' check failed");

	dataChunkData.dataLength = Util::ENDIAN32(dataChunkData.dataLength);
	//-------------------------------------------------------------
	// Raw sound data
	RawSample* pRawSample( new RawSample );
	u8* pData = (u8*)memalign(32, dataChunkData.dataLength );
	fread(pData, 1, dataChunkData.dataLength, WAVFile);
	fmtChunkData.BitResolution = Util::ENDIAN16(fmtChunkData.BitResolution);
	pRawSample->SetRawData(pData);
	pRawSample->SetRawDataLength(dataChunkData.dataLength);


	if (fmtChunkData.BitResolution == 16 )
	{
		if (fmtChunkData.Channels == 1)
			pRawSample->SetNumberOfChannels(VOICE_MONO_16BIT);
		else
			pRawSample->SetNumberOfChannels(VOICE_STEREO_16BIT);
	}
	else
	{
		if (fmtChunkData.Channels == 1)
			pRawSample->SetNumberOfChannels(VOICE_MONO_8BIT);
		else
			pRawSample->SetNumberOfChannels(VOICE_STEREO_8BIT);
	}

	pRawSample->SetSampleRate(fmtChunkData.SampleRate);
	pRawSample->SetBitsPerSample(fmtChunkData.BitResolution);
	//printf("dataLength %d",dataChunkData.dataLength);
	//printf("Channels %d",fmtChunkData.Channels);
	//printf("SampleRate %d",fmtChunkData.SampleRate);
	//printf("BitResolution %d",fmtChunkData.BitResolution);
	//-------------------------------------------------------------
	u16* pData16 = (u16*)pData;
	if (fmtChunkData.BitResolution == 16) // 8 or 16 bit samples - anything other than 16 is just seen as 8 bit
	{
		for (u32 i(0); i = Util::ENDIAN16(pData16);
 		}
 	}
 
 	fclose ( WAVFile );
 	m_SoundContainer[ (HashLabel)LookUpName ] = pRawSample ;
 }
 
 // StoreSoundFromOgg is a supporting function for LoadSound
 void SoundManager::StoreSoundFromOgg(std::string FullFileNameWithPath,std::string LookUpName)
 { 
 	//printf("start ogg");
 
 	char PCM_Out[4096]; // quick working fudge - todo make it dynamic
 	OggVorbis_File vf;
 
 	int current_section;
 
 	if(ov_open(  WiiFile::FileOpenForRead( FullFileNameWithPath.c_str() ) , &vf, NULL, 0) < 0) 
 	{
 		ExitPrintf("Not a Ogg file\n");
 	}
 
 	//	We're going to pull the channel and bitrate info from the file using ov_info() 
 	//and show them to the user. We also want to pull out and show the user a comment attached to the file using ov_comment(). 
 	
 		char **ptr=ov_comment(&vf,-1)->user_comments;
		vorbis_info *vi=ov_info(&vf,-1);
		while(*ptr){
			fprintf(stderr,"%s\n",*ptr);
			++ptr;
		}
		//printf("\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
		//printf("\nDecoded length: %ld samples\n",(long)ov_pcm_total(&vf,-1));
		//printf("Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor);
		//printf("--------");
		//printf("%ld", ((long)ov_pcm_total(&vf,-1)) * vi->channels * (int)sizeof(u16) );
		//printf("--------");
	
	// Raw sound data
	RawSample* pRawSample( new RawSample );
	int RawDataLength = ((long)ov_pcm_total(&vf,-1)) * vi->channels * (int)sizeof(u16);

	int NumberOfChannels = VOICE_STEREO_16BIT;
	if (vi->channels==1)
		NumberOfChannels = VOICE_MONO_16BIT;

	int SampleRate = vi->rate;
	int BitsPerSample = 16; //sizeof(u16);

	RawDataLength/=2;

	u8* pRawData = (u8*)memalign(32, RawDataLength );
	if (pRawData==NULL)
	{
		ExitPrintf("memalign NULL");
	}

	u8* pTemp = pRawData;

	int eof=0;
	int CheckTotal=0;
	while(!eof)
	{
		long ret=ov_read(&vf,PCM_Out,sizeof(PCM_Out),¤t_section);
		if (ret == 0) 
		{
			eof=1;
		} 
		else if (ret < 0) // error in the stream
		{
		} 
		else // we don't bother dealing with sample rate changes, etc, but you'll have to
		{
			if (CheckTotal>=RawDataLength)
			{
				//printf("half");
				break;
			}
			memcpy(pTemp, PCM_Out, ret) ;//fwrite(PCM_Out,1,ret,pOutFile);
			pTemp+=ret;
			CheckTotal += ret;
		}
	}
	ov_clear(&vf);

	//printf("SampleRate  %d",SampleRate);
	//printf("SampleRate  %d",BitsPerSample);
	//printf("SampleRate  %d",NumberOfChannels);
	//printf("SampleRate  %d",RawDataLength);

	pRawSample->SetRawData(pRawData);
	pRawSample->SetRawDataLength(RawDataLength);
	pRawSample->SetNumberOfChannels(NumberOfChannels);
	pRawSample->SetSampleRate(SampleRate);
	pRawSample->SetBitsPerSample(BitsPerSample);
	//-------------------------------------------------------------

	m_SoundContainer[ (HashLabel)LookUpName ] = pRawSample ;
}





Edited 1 time(s). Last edit at 07/12/2011 09:23AM by Titmouse.
Sorry, only registered users may post in this forum.

Click here to login