Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsound_t.h"
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <errno.h></errno.h>
Toshihiro Shimizu 890ddd
#include <unistd.h></unistd.h>
Toshihiro Shimizu 890ddd
#include <queue></queue>
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <coreservices coreservices.h=""></coreservices>
Toshihiro Shimizu 890ddd
#include <audiounit audiounit.h=""></audiounit>
Toshihiro Shimizu 890ddd
#include <coreaudio coreaudio.h=""></coreaudio>
Toshihiro Shimizu 890ddd
#include <audiotoolbox audiotoolbox.h=""></audiotoolbox>
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
TThread::Mutex MutexOut;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 94f329
class TSoundOutputDeviceImp : public std::enable_shared_from_this<tsoundoutputdeviceimp></tsoundoutputdeviceimp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	bool m_isPlaying;
Toshihiro Shimizu 890ddd
	bool m_looped;
Toshihiro Shimizu 890ddd
	TSoundTrackFormat m_currentFormat;
Toshihiro Shimizu 890ddd
	std::set<int> m_supportedRate;</int>
Toshihiro Shimizu 890ddd
	bool m_opened;
Toshihiro Shimizu 890ddd
	AudioFileID musicFileID;
Toshihiro Shimizu 890ddd
	AudioUnit theOutputUnit;
Toshihiro Shimizu 890ddd
	AudioStreamBasicDescription fileASBD;
Toshihiro Shimizu 890ddd
	AudioStreamBasicDescription outputASBD;
Toshihiro Shimizu 890ddd
	AudioConverterRef converter;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceImp()
Toshihiro Shimizu 890ddd
		: m_isPlaying(false), m_looped(false), m_supportedRate(), m_opened(false){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<tsoundoutputdevicelistener *=""> m_listeners;</tsoundoutputdevicelistener>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~TSoundOutputDeviceImp(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doOpenDevice();
Toshihiro Shimizu 890ddd
	bool doSetStreamFormat(const TSoundTrackFormat &format);
Toshihiro Shimizu 890ddd
	bool doStopDevice();
Toshihiro Shimizu 890ddd
	void play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct MyData {
Toshihiro Shimizu 890ddd
	char *entireFileBuffer;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UInt64 totalPacketCount;
Toshihiro Shimizu 890ddd
	UInt64 fileByteCount;
Toshihiro Shimizu 890ddd
	UInt32 maxPacketSize;
Toshihiro Shimizu 890ddd
	UInt64 packetOffset;
Toshihiro Shimizu 890ddd
	UInt64 byteOffset;
Toshihiro Shimizu 890ddd
	bool m_doNotify;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void *sourceBuffer;
Toshihiro Shimizu 890ddd
	AudioConverterRef converter;
Shinya Kitaoka 94f329
	std::shared_ptr<tsoundoutputdeviceimp> imp;</tsoundoutputdeviceimp>
Toshihiro Shimizu 890ddd
	bool isLooping;
Toshihiro Shimizu 890ddd
	MyData()
Shinya Kitaoka 94f329
		: entireFileBuffer(0)
Shinya Kitaoka 94f329
		, totalPacketCount(0)
Shinya Kitaoka 94f329
		, fileByteCount(0)
Shinya Kitaoka 94f329
		, maxPacketSize(0)
Shinya Kitaoka 94f329
		, packetOffset(0)
Shinya Kitaoka 94f329
		, byteOffset(0)
Shinya Kitaoka 94f329
		, sourceBuffer(0)
Shinya Kitaoka 94f329
		, isLooping(false)
Shinya Kitaoka 94f329
		, m_doNotify(true)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PlayCompletedMsg : public TThread::Message
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::set<tsoundoutputdevicelistener *=""> m_listeners;</tsoundoutputdevicelistener>
Toshihiro Shimizu 890ddd
	MyData *m_data;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	PlayCompletedMsg(MyData *data)
Toshihiro Shimizu 890ddd
		: m_data(data)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Message *clone() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return new PlayCompletedMsg(*this);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onDeliver()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_data->imp) {
Toshihiro Shimizu 890ddd
			if (m_data->m_doNotify == false)
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
			m_data->m_doNotify = false;
Toshihiro Shimizu 890ddd
			if (m_data->imp->m_isPlaying)
Toshihiro Shimizu 890ddd
				m_data->imp->doStopDevice();
Toshihiro Shimizu 890ddd
			std::set<tsoundoutputdevicelistener *="">::iterator it = m_data->imp->m_listeners.begin();</tsoundoutputdevicelistener>
Toshihiro Shimizu 890ddd
			for (; it != m_data->imp->m_listeners.end(); ++it)
Toshihiro Shimizu 890ddd
				(*it)->onPlayCompleted();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define checkStatus(err)                                                  \
Toshihiro Shimizu 890ddd
	if (err) {                                                            \
Toshihiro Shimizu 890ddd
		printf("Error: 0x%x ->  %s: %d\n", (int)err, __FILE__, __LINE__); \
Toshihiro Shimizu 890ddd
		fflush(stdout);                                                   \
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern "C" {
Toshihiro Shimizu 890ddd
//This is an example of a Input Procedure from a call to AudioConverterFillComplexBuffer.
Toshihiro Shimizu 890ddd
//The total amount of data needed is "ioNumberDataPackets" when this method is first called.
Toshihiro Shimizu 890ddd
//On exit, "ioNumberDataPackets" must be set to the actual amount of data obtained.
Toshihiro Shimizu 890ddd
//Upon completion, all new input data must point to the AudioBufferList in the parameter ( "ioData" )
Toshihiro Shimizu 890ddd
OSStatus MyACComplexInputProc(AudioConverterRef inAudioConverter,
Toshihiro Shimizu 890ddd
							  UInt32 *ioNumberDataPackets,
Toshihiro Shimizu 890ddd
							  AudioBufferList *ioData,
Toshihiro Shimizu 890ddd
							  AudioStreamPacketDescription **outDataPacketDescription,
Toshihiro Shimizu 890ddd
							  void *inUserData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	OSStatus err = noErr;
Toshihiro Shimizu 890ddd
	UInt32 bytesCopied = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MyData *myData = static_cast<mydata *="">(inUserData);</mydata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// initialize in case of failure
Toshihiro Shimizu 890ddd
	ioData->mBuffers[0].mData = NULL;
Toshihiro Shimizu 890ddd
	ioData->mBuffers[0].mDataByteSize = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
		if (myData->imp->m_isPlaying == false)
Toshihiro Shimizu 890ddd
			return noErr;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// if there are not enough packets to satisfy request, then read what's left
Toshihiro Shimizu 890ddd
	if (myData->packetOffset + *ioNumberDataPackets > myData->totalPacketCount)
Toshihiro Shimizu 890ddd
		*ioNumberDataPackets = myData->totalPacketCount - myData->packetOffset;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// do nothing if there are no packets available
Toshihiro Shimizu 890ddd
	if (*ioNumberDataPackets) {
Toshihiro Shimizu 890ddd
		if (myData->sourceBuffer != NULL) {
Toshihiro Shimizu 890ddd
			free(myData->sourceBuffer);
Toshihiro Shimizu 890ddd
			myData->sourceBuffer = NULL;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//the total amount of data requested by the AudioConverter
Toshihiro Shimizu 890ddd
		bytesCopied = *ioNumberDataPackets * myData->maxPacketSize;
Toshihiro Shimizu 890ddd
		//alloc a small buffer for the AudioConverter to use.
Toshihiro Shimizu 890ddd
		myData->sourceBuffer = (void *)calloc(1, bytesCopied);
Toshihiro Shimizu 890ddd
		//copy the amount of data needed (bytesCopied) from buffer of audio file
Toshihiro Shimizu 890ddd
		memcpy(myData->sourceBuffer, myData->entireFileBuffer + myData->byteOffset, bytesCopied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// keep track of where we want to read from next time
Toshihiro Shimizu 890ddd
		myData->byteOffset += *ioNumberDataPackets * myData->maxPacketSize;
Toshihiro Shimizu 890ddd
		myData->packetOffset += *ioNumberDataPackets;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ioData->mBuffers[0].mData = myData->sourceBuffer; // tell the Audio Converter where it's source data is
Toshihiro Shimizu 890ddd
		ioData->mBuffers[0].mDataByteSize = bytesCopied;  // tell the Audio Converter how much data in each buffer
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// there aren't any more packets to read.
Toshihiro Shimizu 890ddd
		// Set the amount of data read (mDataByteSize) to zero
Toshihiro Shimizu 890ddd
		// and return noErr to signal the AudioConverter there are
Toshihiro Shimizu 890ddd
		// no packets left.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ioData->mBuffers[0].mData = NULL;
Toshihiro Shimizu 890ddd
		ioData->mBuffers[0].mDataByteSize = 0;
Toshihiro Shimizu 890ddd
		delete[] myData->entireFileBuffer;
Toshihiro Shimizu 890ddd
		myData->entireFileBuffer = 0;
Toshihiro Shimizu 890ddd
		err = noErr;
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
  TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
  *(myData->isPlaying) = false;   //questo lo faccio nel main thread
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
		PlayCompletedMsg(myData).send();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
OSStatus MyFileRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags,
Toshihiro Shimizu 890ddd
						  const AudioTimeStamp *inTimeStamp,
Toshihiro Shimizu 890ddd
						  UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MyData *myData = static_cast<mydata *="">(inRefCon);</mydata>
Toshihiro Shimizu 890ddd
	OSStatus err = noErr;
Toshihiro Shimizu 890ddd
	void *inInputDataProcUserData = inRefCon;
Toshihiro Shimizu 890ddd
	AudioStreamPacketDescription *outPacketDescription = NULL;
Toshihiro Shimizu 890ddd
	//To obtain a data buffer of converted data from a complex input source(compressed files, etc.)
Toshihiro Shimizu 890ddd
	//use AudioConverterFillComplexBuffer.  The total amount of data requested is "inNumFrames" and
Toshihiro Shimizu 890ddd
	//on return is set to the actual amount of data recieved.
Toshihiro Shimizu 890ddd
	//All converted data is returned to "ioData" (AudioBufferList).
Toshihiro Shimizu 890ddd
	err = AudioConverterFillComplexBuffer(myData->converter, MyACComplexInputProc, inInputDataProcUserData, &inNumFrames, ioData, outPacketDescription);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*Parameters for AudioConverterFillComplexBuffer()
Toshihiro Shimizu 890ddd
converter - the converter being used
Toshihiro Shimizu 890ddd
ACComplexInputProc() - input procedure to supply data to the Audio Converter
Toshihiro Shimizu 890ddd
inInputDataProcUserData - Used to hold any data that needs to be passed on.  Not needed in this example.
Toshihiro Shimizu 890ddd
inNumFrames - The amount of requested data.  On output, this
Toshihiro Shimizu 890ddd
number is the amount actually received.
Toshihiro Shimizu 890ddd
ioData - Buffer of the converted data recieved on return
Toshihiro Shimizu 890ddd
outPacketDescription - contains the format of the returned data.  Not used in this example.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//checkStatus(err);
Toshihiro Shimizu 890ddd
	return err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //extern "C"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!inDesc) {
Toshihiro Shimizu 890ddd
		printf("Can't print a NULL desc!\n");
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	printf("- - - - - - - - - - - - - - - - - - - -\n");
Toshihiro Shimizu 890ddd
	printf("  Sample Rate:%f\n", inDesc->mSampleRate);
Toshihiro Shimizu 890ddd
	printf("  Format ID:%.*s\n", (int)sizeof(inDesc->mFormatID), (char *)&inDesc->mFormatID);
Toshihiro Shimizu 890ddd
	printf("  Format Flags:%lX\n", inDesc->mFormatFlags);
Toshihiro Shimizu 890ddd
	printf("  Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
Toshihiro Shimizu 890ddd
	printf("  Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
Toshihiro Shimizu 890ddd
	printf("  Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
Toshihiro Shimizu 890ddd
	printf("  Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
Toshihiro Shimizu 890ddd
	printf("  Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
Toshihiro Shimizu 890ddd
	printf("- - - - - - - - - - - - - - - - - - - -\n");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::doOpenDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_opened = false;
Toshihiro Shimizu 890ddd
	OSStatus err = noErr;
Toshihiro Shimizu 890ddd
	ComponentDescription desc;
Toshihiro Shimizu 890ddd
	Component comp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	desc.componentType = kAudioUnitType_Output;
Toshihiro Shimizu 890ddd
	desc.componentSubType = kAudioUnitSubType_DefaultOutput;
Toshihiro Shimizu 890ddd
	//all Audio Units in AUComponent.h must use "kAudioUnitManufacturer_Apple" as the Manufacturer
Toshihiro Shimizu 890ddd
	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
Toshihiro Shimizu 890ddd
	desc.componentFlags = 0;
Toshihiro Shimizu 890ddd
	desc.componentFlagsMask = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	comp = FindNextComponent(NULL, &desc); //Finds an component that meets the desc spec's
Toshihiro Shimizu 890ddd
	if (comp == NULL)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	err = OpenAComponent(comp, &theOutputUnit); //gains access to the services provided by the component
Toshihiro Shimizu 890ddd
	if (err)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UInt32 size;
Toshihiro Shimizu 890ddd
	Boolean outWritable;
Toshihiro Shimizu 890ddd
	UInt32 theInputBus = 0;
Toshihiro Shimizu 890ddd
	//Gets the size of the Stream Format Property and if it is writable
Toshihiro Shimizu 890ddd
	err = AudioUnitGetPropertyInfo(theOutputUnit,
Toshihiro Shimizu 890ddd
								   kAudioUnitProperty_StreamFormat,
Toshihiro Shimizu 890ddd
								   kAudioUnitScope_Output,
Toshihiro Shimizu 890ddd
								   0, &size, &outWritable);
Toshihiro Shimizu 890ddd
	//Get the current stream format of the output
Toshihiro Shimizu 890ddd
	err = AudioUnitGetProperty(theOutputUnit,
Toshihiro Shimizu 890ddd
							   kAudioUnitProperty_StreamFormat,
Toshihiro Shimizu 890ddd
							   kAudioUnitScope_Output,
Toshihiro Shimizu 890ddd
							   0, &outputASBD, &size);
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
	//Set the stream format of the output to match the input
Toshihiro Shimizu 890ddd
	err = AudioUnitSetProperty(theOutputUnit,
Toshihiro Shimizu 890ddd
							   kAudioUnitProperty_StreamFormat,
Toshihiro Shimizu 890ddd
							   kAudioUnitScope_Input,
Toshihiro Shimizu 890ddd
							   theInputBus,
Toshihiro Shimizu 890ddd
							   &outputASBD,
Toshihiro Shimizu 890ddd
							   size);
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize AudioUnit, alloc mem buffers for processing
Toshihiro Shimizu 890ddd
	err = AudioUnitInitialize(theOutputUnit);
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
	if (err == noErr)
Toshihiro Shimizu 890ddd
		m_opened = true;
Toshihiro Shimizu 890ddd
	return m_opened;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::doSetStreamFormat(const TSoundTrackFormat &format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_opened)
Toshihiro Shimizu 890ddd
		doOpenDevice();
Toshihiro Shimizu 890ddd
	if (!m_opened)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fileASBD.mSampleRate = format.m_sampleRate;
Toshihiro Shimizu 890ddd
	fileASBD.mFormatID = kAudioFormatLinearPCM;
Toshihiro Shimizu 890ddd
	fileASBD.mFormatFlags = 14;
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
Standard flags: kAudioFormatFlagIsFloat = (1L << 0) 
Toshihiro Shimizu 890ddd
kAudioFormatFlagIsBigEndian = (1L << 1)
Toshihiro Shimizu 890ddd
kAudioFormatFlagIsSignedInteger = (1L << 2)
Toshihiro Shimizu 890ddd
kAudioFormatFlagIsPacked = (1L << 3)
Toshihiro Shimizu 890ddd
kAudioFormatFlagIsAlignedHigh = (1L << 4)
Toshihiro Shimizu 890ddd
kAudioFormatFlagIsNonInterleaved = (1L << 5)
Toshihiro Shimizu 890ddd
kAudioFormatFlagsAreAllClear = (1L << 31)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Linear PCM flags: 
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved
Toshihiro Shimizu 890ddd
kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear 
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
	fileASBD.mBytesPerPacket = (format.m_bitPerSample >> 3) * format.m_channelCount;
Toshihiro Shimizu 890ddd
	fileASBD.mFramesPerPacket = 1;
Toshihiro Shimizu 890ddd
	fileASBD.mBytesPerFrame = (format.m_bitPerSample >> 3) * format.m_channelCount;
Toshihiro Shimizu 890ddd
	fileASBD.mChannelsPerFrame = format.m_channelCount;
Toshihiro Shimizu 890ddd
	fileASBD.mBitsPerChannel = format.m_bitPerSample;
Toshihiro Shimizu 890ddd
	fileASBD.mReserved = 0;
Toshihiro Shimizu 890ddd
	//PrintStreamDesc(&fileASBD);
Toshihiro Shimizu 890ddd
	m_opened = true;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		supportsVolume();
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDevice::~TSoundOutputDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	stop();
Toshihiro Shimizu 890ddd
	close();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::installed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::open(const TSoundTrackP &st)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->doOpenDevice())
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableOpenDevice,
Toshihiro Shimizu 890ddd
			"Problem to open the output device");
Toshihiro Shimizu 890ddd
	if (!m_imp->doSetStreamFormat(st->getFormat()))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableOpenDevice,
Toshihiro Shimizu 890ddd
			"Problem to open the output device setting some params");
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::close()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	stop();
Toshihiro Shimizu 890ddd
	m_imp->m_opened = false;
Toshihiro Shimizu 890ddd
	AudioUnitUninitialize(m_imp->theOutputUnit); //release resources without closing the component
Toshihiro Shimizu 890ddd
	CloseComponent(m_imp->theOutputUnit);		 //Terminates your application's access to the services provided
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
	int lastSample = st->getSampleCount() - 1;
Toshihiro Shimizu 890ddd
	notLessThan(0, s0);
Toshihiro Shimizu 890ddd
	notLessThan(0, s1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	notMoreThan(lastSample, s0);
Toshihiro Shimizu 890ddd
	notMoreThan(lastSample, s1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (s0 > s1) {
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Toshihiro Shimizu 890ddd
		cout << "s0 > s1; reorder" << endl;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		swap(s0, s1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isPlaying()) {
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Toshihiro Shimizu 890ddd
		cout << "is playing, stop it!" << endl;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		stop();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_imp->play(st, s0, s1, loop, scrubbing);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDeviceImp::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!doSetStreamFormat(st->getFormat()))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	OSStatus err = noErr;
Toshihiro Shimizu 890ddd
	MyData *myData = new MyData();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 94f329
	myData->imp = shared_from_this();
Toshihiro Shimizu 890ddd
	UInt32 magicCookieSize = 0;
Toshihiro Shimizu 890ddd
	//PrintStreamDesc(&outputASBD);
Toshihiro Shimizu 890ddd
	err = AudioConverterNew(&fileASBD, &outputASBD, &converter);
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
	err = AudioFileGetPropertyInfo(musicFileID,
Toshihiro Shimizu 890ddd
								   kAudioFilePropertyMagicCookieData,
Toshihiro Shimizu 890ddd
								   &magicCookieSize,
Toshihiro Shimizu 890ddd
								   NULL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (err == noErr) {
Toshihiro Shimizu 890ddd
		void *magicCookie = calloc(1, magicCookieSize);
Toshihiro Shimizu 890ddd
		if (magicCookie) {
Toshihiro Shimizu 890ddd
			//Get Magic Cookie data from Audio File
Toshihiro Shimizu 890ddd
			err = AudioFileGetProperty(musicFileID,
Toshihiro Shimizu 890ddd
									   kAudioFilePropertyMagicCookieData,
Toshihiro Shimizu 890ddd
									   &magicCookieSize,
Toshihiro Shimizu 890ddd
									   magicCookie);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Give the AudioConverter the magic cookie decompression params if there are any
Toshihiro Shimizu 890ddd
			if (err == noErr) {
Toshihiro Shimizu 890ddd
				err = AudioConverterSetProperty(myData->converter,
Toshihiro Shimizu 890ddd
												kAudioConverterDecompressionMagicCookie,
Toshihiro Shimizu 890ddd
												magicCookieSize,
Toshihiro Shimizu 890ddd
												magicCookie);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			err = noErr;
Toshihiro Shimizu 890ddd
			if (magicCookie)
Toshihiro Shimizu 890ddd
				free(magicCookie);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else //this is OK because some audio data doesn't need magic cookie data
Toshihiro Shimizu 890ddd
		err = noErr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
	myData->converter = converter;
Toshihiro Shimizu 890ddd
	myData->totalPacketCount = s1 - s0;
Toshihiro Shimizu 890ddd
	myData->fileByteCount = (s1 - s0) * st->getSampleSize();
Toshihiro Shimizu 890ddd
	myData->entireFileBuffer = new char[myData->fileByteCount];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(i386)
Toshihiro Shimizu 890ddd
	if (st->getBitPerSample() == 16) {
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		USHORT *dst = (USHORT *)(myData->entireFileBuffer);
Toshihiro Shimizu 890ddd
		USHORT *src = (USHORT *)(st->getRawData() + s0 * st->getSampleSize());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < myData->fileByteCount / 2; i++)
Toshihiro Shimizu 890ddd
			*dst++ = swapUshort(*src++);
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		memcpy(myData->entireFileBuffer, st->getRawData() + s0 * st->getSampleSize(), myData->fileByteCount);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	memcpy(myData->entireFileBuffer, st->getRawData() + s0 * st->getSampleSize(), myData->fileByteCount);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	myData->maxPacketSize = fileASBD.mFramesPerPacket * fileASBD.mBytesPerFrame;
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
		m_isPlaying = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	myData->isLooping = loop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//cout << "total packet count = " << myData->totalPacketCount <
Toshihiro Shimizu 890ddd
	//cout << "filebytecount " << myData->fileByteCount << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	AURenderCallbackStruct renderCallback;
Toshihiro Shimizu 890ddd
	memset(&renderCallback, 0, sizeof(AURenderCallbackStruct));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	renderCallback.inputProc = MyFileRenderProc;
Toshihiro Shimizu 890ddd
	renderCallback.inputProcRefCon = myData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Sets the callback for the Audio Unit to the renderCallback
Toshihiro Shimizu 890ddd
	err = AudioUnitSetProperty(theOutputUnit,
Toshihiro Shimizu 890ddd
							   kAudioUnitProperty_SetRenderCallback,
Toshihiro Shimizu 890ddd
							   kAudioUnitScope_Input,
Toshihiro Shimizu 890ddd
							   0, &renderCallback,
Toshihiro Shimizu 890ddd
							   sizeof(AURenderCallbackStruct));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	err = AudioOutputUnitStart(theOutputUnit);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	checkStatus(err);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::doStopDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_isPlaying = false;
Toshihiro Shimizu 890ddd
	AudioOutputUnitStop(theOutputUnit); //you must stop the audio unit from processing
Toshihiro Shimizu 890ddd
	AudioConverterDispose(converter);   //deallocates the memory used by inAudioConverter
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::stop()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
	if (m_imp->m_opened == false)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
	m_imp->doStopDevice();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_listeners.insert(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_listeners.erase(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TSoundOutputDevice::getVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->m_opened)
Toshihiro Shimizu 890ddd
		m_imp->doOpenDevice();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Float32 leftVol, rightVol;
Toshihiro Shimizu 890ddd
	AudioUnitGetParameter(
Toshihiro Shimizu 890ddd
		m_imp->theOutputUnit,
Toshihiro Shimizu 890ddd
		kHALOutputParam_Volume,
Toshihiro Shimizu 890ddd
		kAudioUnitScope_Output,
Toshihiro Shimizu 890ddd
		0,
Toshihiro Shimizu 890ddd
		&leftVol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	AudioUnitGetParameter(
Toshihiro Shimizu 890ddd
		m_imp->theOutputUnit,
Toshihiro Shimizu 890ddd
		kHALOutputParam_Volume,
Toshihiro Shimizu 890ddd
		kAudioUnitScope_Output,
Toshihiro Shimizu 890ddd
		0,
Toshihiro Shimizu 890ddd
		&rightVol);
Toshihiro Shimizu 890ddd
	double vol = (leftVol + rightVol) / 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (vol < 0. ? 0. : vol);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::setVolume(double volume)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Float32 vol = volume;
Toshihiro Shimizu 890ddd
	AudioUnitSetParameter(
Toshihiro Shimizu 890ddd
		m_imp->theOutputUnit,
Toshihiro Shimizu 890ddd
		kHALOutputParam_Volume,
Toshihiro Shimizu 890ddd
		kAudioUnitScope_Output,
Toshihiro Shimizu 890ddd
		0,
Toshihiro Shimizu 890ddd
		vol,
Toshihiro Shimizu 890ddd
		0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	AudioUnitSetParameter(
Toshihiro Shimizu 890ddd
		m_imp->theOutputUnit,
Toshihiro Shimizu 890ddd
		kHALOutputParam_Volume,
Toshihiro Shimizu 890ddd
		kAudioUnitScope_Output,
Toshihiro Shimizu 890ddd
		0,
Toshihiro Shimizu 890ddd
		vol,
Toshihiro Shimizu 890ddd
		0);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::supportsVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::isPlaying() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
	return m_imp->m_isPlaying;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::isLooping()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
	return m_imp->m_looped;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::setLooping(bool loop)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TThread::ScopedLock sl(MutexOut);
Toshihiro Shimizu 890ddd
	m_imp->m_looped = loop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(
Toshihiro Shimizu 890ddd
	TUINT32 sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt(
Toshihiro Shimizu 890ddd
		sampleRate,
Toshihiro Shimizu 890ddd
		bitPerSample,
Toshihiro Shimizu 890ddd
		channelCount,
Toshihiro Shimizu 890ddd
		true);
Toshihiro Shimizu 890ddd
	return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat &format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// try {
Toshihiro Shimizu 890ddd
	return getPreferredFormat(
Toshihiro Shimizu 890ddd
		format.m_sampleRate, format.m_channelCount, format.m_bitPerSample);
Toshihiro Shimizu 890ddd
	/*}
Toshihiro Shimizu 890ddd
  catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
    throw TSoundDeviceException( e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
  }*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//                REGISTRAZIONE
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TSoundInputDeviceImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	//ALport m_port;
Toshihiro Shimizu 890ddd
	bool m_stopped;
Toshihiro Shimizu 890ddd
	bool m_isRecording;
Toshihiro Shimizu 890ddd
	bool m_oneShotRecording;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	long m_recordedSampleCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundTrackFormat m_currentFormat;
Toshihiro Shimizu 890ddd
	TSoundTrackP m_st;
Toshihiro Shimizu 890ddd
	std::set<int> m_supportedRate;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Executor m_executor;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundInputDeviceImp()
Toshihiro Shimizu 890ddd
		: m_stopped(false), m_isRecording(false)
Toshihiro Shimizu 890ddd
		  //   , m_port(NULL)
Toshihiro Shimizu 890ddd
		  ,
Toshihiro Shimizu 890ddd
		  m_oneShotRecording(false), m_recordedSampleCount(0), m_st(0), m_supportedRate(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~TSoundInputDeviceImp(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doOpenDevice(const TSoundTrackFormat &format,
Toshihiro Shimizu 890ddd
					  TSoundInputDevice::Source devType);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDeviceImp::doOpenDevice(const TSoundTrackFormat &format,
Toshihiro Shimizu 890ddd
										TSoundInputDevice::Source devType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class RecordTask : public TThread::Runnable
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TSoundInputDeviceImp *m_devImp;
Toshihiro Shimizu 890ddd
	int m_ByteToSample;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	RecordTask(TSoundInputDeviceImp *devImp, int numByte)
Toshihiro Shimizu 890ddd
		: TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~RecordTask(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void run();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RecordTask::run()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundInputDevice::~TSoundInputDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::installed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
	if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <=0)
Toshihiro Shimizu 890ddd
    return false;
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDevice::record(const TSoundTrackFormat &format, TSoundInputDevice::Source type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDevice::record(const TSoundTrackP &st, TSoundInputDevice::Source type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackP TSoundInputDevice::stop()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackP st;
Toshihiro Shimizu 890ddd
	return st;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TSoundInputDevice::getVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return 0.0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::setVolume(double volume)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::supportsVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(
Toshihiro Shimizu 890ddd
	TUINT32 sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
	return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(const TSoundTrackFormat &format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  try {
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	return getPreferredFormat(
Toshihiro Shimizu 890ddd
		format.m_sampleRate, format.m_channelCount, format.m_bitPerSample);
Toshihiro Shimizu 890ddd
	/*}
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
    throw TSoundDeviceException( e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::isRecording()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_isRecording;
Toshihiro Shimizu 890ddd
}