Fix for sierra scrub crash (#1302)

* fix for sierra scrub crash
This commit is contained in:
Jeremy Bullock 2017-09-22 01:19:10 -06:00 committed by shun-iwasawa
parent 25e6cfef72
commit 6767bee6b3
5 changed files with 114 additions and 341 deletions

View file

@ -10,10 +10,11 @@
#include <queue>
#include <set>
#include <CoreServices/CoreServices.h>
#include <AudioUnit/AudioUnit.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QByteArray>
#include <QAudioFormat>
#include <QBuffer>
#include <QAudioOutput>
using namespace std;
//==============================================================================
@ -29,11 +30,10 @@ public:
TSoundTrackFormat m_currentFormat;
std::set<int> m_supportedRate;
bool m_opened;
AudioFileID musicFileID;
AudioUnit theOutputUnit;
AudioStreamBasicDescription fileASBD;
AudioStreamBasicDescription outputASBD;
AudioConverterRef converter;
double m_volume = 0.5;
QAudioOutput *m_audioOutput;
QBuffer *m_buffer;
TSoundOutputDeviceImp()
: m_isPlaying(false)
@ -50,6 +50,7 @@ public:
bool doStopDevice();
void play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop,
bool scrubbing);
void prepareVolume(double volume);
};
//-----------------------------------------------------------------------------
@ -58,15 +59,14 @@ namespace {
struct MyData {
char *entireFileBuffer;
UInt64 totalPacketCount;
UInt64 fileByteCount;
UInt32 maxPacketSize;
UInt64 packetOffset;
UInt64 byteOffset;
quint64 totalPacketCount;
quint64 fileByteCount;
quint32 maxPacketSize;
quint64 packetOffset;
quint64 byteOffset;
bool m_doNotify;
void *sourceBuffer;
AudioConverterRef converter;
// AudioConverterRef converter;
std::shared_ptr<TSoundOutputDeviceImp> imp;
bool isLooping;
MyData()
@ -110,218 +110,16 @@ public:
fflush(stdout); \
}
extern "C" {
// This is an example of a Input Procedure from a call to
// AudioConverterFillComplexBuffer.
// The total amount of data needed is "ioNumberDataPackets" when this method is
// first called.
// On exit, "ioNumberDataPackets" must be set to the actual amount of data
// obtained.
// Upon completion, all new input data must point to the AudioBufferList in the
// parameter ( "ioData" )
OSStatus MyACComplexInputProc(
AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) {
OSStatus err = noErr;
UInt32 bytesCopied = 0;
MyData *myData = static_cast<MyData *>(inUserData);
// initialize in case of failure
ioData->mBuffers[0].mData = NULL;
ioData->mBuffers[0].mDataByteSize = 0;
{
// TThread::ScopedLock sl(MutexOut);
if (myData->imp->m_isPlaying == false) return noErr;
}
// if there are not enough packets to satisfy request, then read what's left
if (myData->packetOffset + *ioNumberDataPackets > myData->totalPacketCount)
*ioNumberDataPackets = myData->totalPacketCount - myData->packetOffset;
// do nothing if there are no packets available
if (*ioNumberDataPackets) {
if (myData->sourceBuffer != NULL) {
free(myData->sourceBuffer);
myData->sourceBuffer = NULL;
}
// the total amount of data requested by the AudioConverter
bytesCopied = *ioNumberDataPackets * myData->maxPacketSize;
// alloc a small buffer for the AudioConverter to use.
myData->sourceBuffer = (void *)calloc(1, bytesCopied);
// copy the amount of data needed (bytesCopied) from buffer of audio file
memcpy(myData->sourceBuffer, myData->entireFileBuffer + myData->byteOffset,
bytesCopied);
// keep track of where we want to read from next time
myData->byteOffset += *ioNumberDataPackets * myData->maxPacketSize;
myData->packetOffset += *ioNumberDataPackets;
ioData->mBuffers[0].mData = myData->sourceBuffer; // tell the Audio
// Converter where it's
// source data is
ioData->mBuffers[0].mDataByteSize =
bytesCopied; // tell the Audio Converter how much data in each buffer
} else {
// there aren't any more packets to read.
// Set the amount of data read (mDataByteSize) to zero
// and return noErr to signal the AudioConverter there are
// no packets left.
ioData->mBuffers[0].mData = NULL;
ioData->mBuffers[0].mDataByteSize = 0;
delete[] myData->entireFileBuffer;
myData->entireFileBuffer = 0;
err = noErr;
/*
{
TThread::ScopedLock sl(MutexOut);
*(myData->isPlaying) = false; //questo lo faccio nel main thread
}
*/
PlayCompletedMsg(myData).send();
}
return err;
}
OSStatus MyFileRenderProc(void *inRefCon,
AudioUnitRenderActionFlags *inActionFlags,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
UInt32 inNumFrames, AudioBufferList *ioData) {
MyData *myData = static_cast<MyData *>(inRefCon);
OSStatus err = noErr;
void *inInputDataProcUserData = inRefCon;
AudioStreamPacketDescription *outPacketDescription = NULL;
// To obtain a data buffer of converted data from a complex input
// source(compressed files, etc.)
// use AudioConverterFillComplexBuffer. The total amount of data requested is
// "inNumFrames" and
// on return is set to the actual amount of data recieved.
// All converted data is returned to "ioData" (AudioBufferList).
err = AudioConverterFillComplexBuffer(myData->converter, MyACComplexInputProc,
inInputDataProcUserData, &inNumFrames,
ioData, outPacketDescription);
/*Parameters for AudioConverterFillComplexBuffer()
converter - the converter being used
ACComplexInputProc() - input procedure to supply data to the Audio Converter
inInputDataProcUserData - Used to hold any data that needs to be passed on. Not
needed in this example.
inNumFrames - The amount of requested data. On output, this
number is the amount actually received.
ioData - Buffer of the converted data recieved on return
outPacketDescription - contains the format of the returned data. Not used in
this example.
*/
// checkStatus(err);
return err;
}
} // extern "C"
void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
if (!inDesc) {
printf("Can't print a NULL desc!\n");
return;
}
printf("- - - - - - - - - - - - - - - - - - - -\n");
printf(" Sample Rate:%f\n", inDesc->mSampleRate);
printf(" Format ID:%.*s\n", (int)sizeof(inDesc->mFormatID),
(char *)&inDesc->mFormatID);
printf(" Format Flags:%lX\n", inDesc->mFormatFlags);
printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
printf("- - - - - - - - - - - - - - - - - - - -\n");
}
bool TSoundOutputDeviceImp::doOpenDevice() {
m_opened = false;
OSStatus err = noErr;
ComponentDescription desc;
Component comp;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
// all Audio Units in AUComponent.h must use "kAudioUnitManufacturer_Apple" as
// the Manufacturer
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
comp = FindNextComponent(
NULL, &desc); // Finds an component that meets the desc spec's
if (comp == NULL) return false;
err = OpenAComponent(comp, &theOutputUnit); // gains access to the services
// provided by the component
if (err) return false;
UInt32 size;
Boolean outWritable;
UInt32 theInputBus = 0;
// Gets the size of the Stream Format Property and if it is writable
err =
AudioUnitGetPropertyInfo(theOutputUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &size, &outWritable);
// Get the current stream format of the output
err = AudioUnitGetProperty(theOutputUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &outputASBD, &size);
checkStatus(err);
// Set the stream format of the output to match the input
err = AudioUnitSetProperty(theOutputUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, theInputBus, &outputASBD,
size);
checkStatus(err);
// Initialize AudioUnit, alloc mem buffers for processing
err = AudioUnitInitialize(theOutputUnit);
checkStatus(err);
if (err == noErr) m_opened = true;
m_opened = false;
m_audioOutput = NULL;
m_opened = true;
return m_opened;
}
bool TSoundOutputDeviceImp::doSetStreamFormat(const TSoundTrackFormat &format) {
if (!m_opened) doOpenDevice();
if (!m_opened) return false;
fileASBD.mSampleRate = format.m_sampleRate;
fileASBD.mFormatID = kAudioFormatLinearPCM;
fileASBD.mFormatFlags = 14;
/*
Standard flags: kAudioFormatFlagIsFloat = (1L << 0)
kAudioFormatFlagIsBigEndian = (1L << 1)
kAudioFormatFlagIsSignedInteger = (1L << 2)
kAudioFormatFlagIsPacked = (1L << 3)
kAudioFormatFlagIsAlignedHigh = (1L << 4)
kAudioFormatFlagIsNonInterleaved = (1L << 5)
kAudioFormatFlagsAreAllClear = (1L << 31)
Linear PCM flags:
kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat
kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian
kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger
kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked
kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh
kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved
kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear
*/
fileASBD.mBytesPerPacket =
(format.m_bitPerSample >> 3) * format.m_channelCount;
fileASBD.mFramesPerPacket = 1;
fileASBD.mBytesPerFrame =
(format.m_bitPerSample >> 3) * format.m_channelCount;
fileASBD.mChannelsPerFrame = format.m_channelCount;
fileASBD.mBitsPerChannel = format.m_bitPerSample;
fileASBD.mReserved = 0;
// PrintStreamDesc(&fileASBD);
m_opened = true;
return true;
}
@ -365,18 +163,25 @@ bool TSoundOutputDevice::open(const TSoundTrackP &st) {
bool TSoundOutputDevice::close() {
stop();
m_imp->m_opened = false;
AudioUnitUninitialize(
m_imp->theOutputUnit); // release resources without closing the component
CloseComponent(m_imp->theOutputUnit); // Terminates your application's access
// to the services provided
return true;
}
//------------------------------------------------------------------------------
void TSoundOutputDeviceImp::prepareVolume(double volume) {
m_volume = volume;
}
//------------------------------------------------------------------------------
void TSoundOutputDevice::prepareVolume(double volume) {
m_imp->prepareVolume(volume);
}
//------------------------------------------------------------------------------
void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1,
bool loop, bool scrubbing) {
// TThread::ScopedLock sl(MutexOut);
int lastSample = st->getSampleCount() - 1;
notLessThan(0, s0);
notLessThan(0, s1);
@ -406,105 +211,72 @@ void TSoundOutputDeviceImp::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1,
bool loop, bool scrubbing) {
if (!doSetStreamFormat(st->getFormat())) return;
OSStatus err = noErr;
MyData *myData = new MyData();
myData->imp = shared_from_this();
UInt32 magicCookieSize = 0;
// PrintStreamDesc(&outputASBD);
err = AudioConverterNew(&fileASBD, &outputASBD, &converter);
checkStatus(err);
err = AudioFileGetPropertyInfo(musicFileID, kAudioFilePropertyMagicCookieData,
&magicCookieSize, NULL);
if (err == noErr) {
void *magicCookie = calloc(1, magicCookieSize);
if (magicCookie) {
// Get Magic Cookie data from Audio File
err = AudioFileGetProperty(musicFileID, kAudioFilePropertyMagicCookieData,
&magicCookieSize, magicCookie);
// Give the AudioConverter the magic cookie decompression params if there
// are any
if (err == noErr) {
err = AudioConverterSetProperty(myData->converter,
kAudioConverterDecompressionMagicCookie,
magicCookieSize, magicCookie);
}
err = noErr;
if (magicCookie) free(magicCookie);
}
} else // this is OK because some audio data doesn't need magic cookie data
err = noErr;
checkStatus(err);
myData->converter = converter;
myData->imp = shared_from_this();
myData->totalPacketCount = s1 - s0;
myData->fileByteCount = (s1 - s0) * st->getSampleSize();
myData->entireFileBuffer = new char[myData->fileByteCount];
#if defined(i386)
if (st->getBitPerSample() == 16) {
int i;
USHORT *dst = (USHORT *)(myData->entireFileBuffer);
USHORT *src = (USHORT *)(st->getRawData() + s0 * st->getSampleSize());
for (i = 0; i < myData->fileByteCount / 2; i++) *dst++ = swapUshort(*src++);
} else
memcpy(myData->entireFileBuffer,
st->getRawData() + s0 * st->getSampleSize(), myData->fileByteCount);
#else
memcpy(myData->entireFileBuffer, st->getRawData() + s0 * st->getSampleSize(),
myData->fileByteCount);
#endif
myData->maxPacketSize = fileASBD.mFramesPerPacket * fileASBD.mBytesPerFrame;
{
// TThread::ScopedLock sl(MutexOut);
m_isPlaying = true;
}
m_isPlaying = true;
myData->isLooping = loop;
// cout << "total packet count = " << myData->totalPacketCount <<endl;
// cout << "filebytecount " << myData->fileByteCount << endl;
QAudioFormat format;
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
AURenderCallbackStruct renderCallback;
memset(&renderCallback, 0, sizeof(AURenderCallbackStruct));
renderCallback.inputProc = MyFileRenderProc;
renderCallback.inputProcRefCon = myData;
// Sets the callback for the Audio Unit to the renderCallback
err =
AudioUnitSetProperty(theOutputUnit, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &renderCallback,
sizeof(AURenderCallbackStruct));
checkStatus(err);
err = AudioOutputUnitStart(theOutputUnit);
checkStatus(err);
format.setSampleSize(st->getBitPerSample());
format.setCodec("audio/pcm");
format.setChannelCount(st->getChannelCount());
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(st->getFormat().m_signedSample
? QAudioFormat::SignedInt
: QAudioFormat::UnSignedInt);
format.setSampleRate(st->getSampleRate());
QList<QAudioFormat::Endian> sbos = info.supportedByteOrders();
QList<int> sccs = info.supportedChannelCounts();
QList<int> ssrs = info.supportedSampleRates();
QList<QAudioFormat::SampleType> sstypes = info.supportedSampleTypes();
QList<int> ssss = info.supportedSampleSizes();
QStringList supCodes = info.supportedCodecs();
if (!info.isFormatSupported((format))) {
format = info.nearestFormat(format);
int newChannels = format.channelCount();
int newBitsPerSample = format.sampleSize();
int newSampleRate = format.sampleRate();
QAudioFormat::SampleType newSampleType = format.sampleType();
QAudioFormat::Endian newBo = format.byteOrder();
}
int test = st->getSampleCount() / st->getSampleRate();
QByteArray *data =
new QByteArray(myData->entireFileBuffer, myData->fileByteCount);
QBuffer *newBuffer = new QBuffer;
newBuffer->setBuffer(data);
newBuffer->open(QIODevice::ReadOnly);
newBuffer->seek(0);
if (m_audioOutput == NULL) {
m_audioOutput = new QAudioOutput(format, NULL);
}
m_audioOutput->start(newBuffer);
m_audioOutput->setVolume(m_volume);
}
//------------------------------------------------------------------------------
bool TSoundOutputDeviceImp::doStopDevice() {
m_isPlaying = false;
AudioOutputUnitStop(
theOutputUnit); // you must stop the audio unit from processing
AudioConverterDispose(
converter); // deallocates the memory used by inAudioConverter
m_audioOutput->stop();
return true;
}
//------------------------------------------------------------------------------
void TSoundOutputDevice::stop() {
// TThread::ScopedLock sl(MutexOut);
if (m_imp->m_opened == false) return;
// TThread::ScopedLock sl(MutexOut);
m_imp->doStopDevice();
}
@ -523,28 +295,16 @@ void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) {
//------------------------------------------------------------------------------
double TSoundOutputDevice::getVolume() {
if (!m_imp->m_opened) m_imp->doOpenDevice();
Float32 leftVol, rightVol;
AudioUnitGetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume,
kAudioUnitScope_Output, 0, &leftVol);
AudioUnitGetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume,
kAudioUnitScope_Output, 0, &rightVol);
double vol = (leftVol + rightVol) / 2;
return (vol < 0. ? 0. : vol);
if (m_imp->m_audioOutput != NULL)
return m_imp->m_audioOutput->volume();
else return m_imp->m_volume;
}
//------------------------------------------------------------------------------
bool TSoundOutputDevice::setVolume(double volume) {
Float32 vol = volume;
AudioUnitSetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume,
kAudioUnitScope_Output, 0, vol, 0);
AudioUnitSetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume,
kAudioUnitScope_Output, 0, vol, 0);
m_imp->m_volume = volume;
m_imp->m_audioOutput->setVolume(volume);
return true;
}
@ -554,24 +314,15 @@ bool TSoundOutputDevice::supportsVolume() { return true; }
//------------------------------------------------------------------------------
bool TSoundOutputDevice::isPlaying() const {
// TThread::ScopedLock sl(MutexOut);
return m_imp->m_isPlaying;
}
bool TSoundOutputDevice::isPlaying() const { return m_imp->m_isPlaying; }
//------------------------------------------------------------------------------
bool TSoundOutputDevice::isLooping() {
// TThread::ScopedLock sl(MutexOut);
return m_imp->m_looped;
}
bool TSoundOutputDevice::isLooping() { return m_imp->m_looped; }
//------------------------------------------------------------------------------
void TSoundOutputDevice::setLooping(bool loop) {
// TThread::ScopedLock sl(MutexOut);
m_imp->m_looped = loop;
}
void TSoundOutputDevice::setLooping(bool loop) { m_imp->m_looped = loop; }
//------------------------------------------------------------------------------
@ -586,13 +337,8 @@ TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(TUINT32 sampleRate,
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(
const TSoundTrackFormat &format) {
// try {
return getPreferredFormat(format.m_sampleRate, format.m_channelCount,
format.m_bitPerSample);
/*}
catch (TSoundDeviceException &e) {
throw TSoundDeviceException( e.getType(), e.getMessage());
}*/
}
//==============================================================================

View file

@ -382,6 +382,7 @@ Returns true if on the machine there is an audio card installed correctly
//! Set the value of volume , between [0,1]
bool setVolume(double value);
void prepareVolume(double volume);
#endif
//! Open the device according to the features of soundtrack

View file

@ -353,7 +353,7 @@ elseif(BUILD_ENV_UNIXLIKE)
endif()
target_link_libraries(tnzcore
Qt5::OpenGL Qt5::Network
Qt5::OpenGL Qt5::Network Qt5::Multimedia
${GL_LIB} ${GLUT_LIB} ${QT_LIB} ${Z_LIB} ${JPEG_LIB} ${LZ4_LIB}
${EXTRA_LIBS}
)

View file

@ -351,7 +351,7 @@ include_directories(
if(BUILD_ENV_MSVC)
target_link_libraries(toonzlib
Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Script
Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Script Qt5::Multimedia
${GLUT_LIB} ${GL_LIB} ${MYPAINT_LIB_LDFLAGS} vfw32.lib
tnzcore tnzbase tnzext
)
@ -364,7 +364,7 @@ elseif(BUILD_ENV_APPLE)
${MYPAINT_LIB_LDFLAGS}
)
target_link_libraries(toonzlib Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Script ${GLUT_LIB} ${GL_LIB} ${EXTRA_LIBS})
target_link_libraries(toonzlib Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Script Qt5::Multimedia ${GLUT_LIB} ${GL_LIB} ${EXTRA_LIBS})
elseif(BUILD_ENV_UNIXLIKE)
_find_toonz_library(EXTRA_LIBS "tnzcore;tnzbase;tnzext")
@ -372,5 +372,5 @@ elseif(BUILD_ENV_UNIXLIKE)
set(EXTRA_LIBS ${EXTRA_LIBS} -lvfw32)
endif()
target_link_libraries(toonzlib Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Script ${GLUT_LIB} ${GL_LIB} ${EXTRA_LIBS} ${MYPAINT_LIB_LDFLAGS})
target_link_libraries(toonzlib Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Script Qt5::Multimedia ${GLUT_LIB} ${GL_LIB} ${EXTRA_LIBS} ${MYPAINT_LIB_LDFLAGS})
endif()

View file

@ -13,6 +13,9 @@
#include "tsop.h"
#include "tconvert.h"
#include <QAudioFormat>
#include <QAudioDeviceInfo>
//=============================================================================
// ColumnLevel
//=============================================================================
@ -806,7 +809,7 @@ void TXshSoundColumn::play(TSoundTrackP soundtrack, int s0, int s1, bool loop) {
if (m_player) {
try {
#ifdef MACOSX
m_player->setVolume(m_volume);
m_player->prepareVolume(m_volume);
TSoundTrackP mixedTrack = soundtrack;
#else
TSoundTrackP mixedTrack = TSoundTrack::create(
@ -997,10 +1000,33 @@ TSoundTrackP TXshSoundColumn::getOverallSoundTrack(int fromFrame, int toFrame,
format.m_signedSample = true;
}
// We prefer to have 22050 as a maximum sampleRate (to avoid crashes or
// another issues)
// We prefer to have 22050 as a maximum sampleRate (to avoid crashes or
// another issues)
#ifndef MACOSX
if (format.m_sampleRate >= 44100) format.m_sampleRate = 22050;
#else
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
QList<int> ssrs = info.supportedSampleRates();
if (!ssrs.contains(format.m_sampleRate)) format.m_sampleRate = 44100;
QAudioFormat qFormat;
qFormat.setSampleRate(format.m_sampleRate);
qFormat.setSampleType(format.m_signedSample ? QAudioFormat::SignedInt
: QAudioFormat::UnSignedInt);
qFormat.setSampleSize(format.m_bitPerSample);
qFormat.setCodec("audio/pcm");
qFormat.setChannelCount(format.m_channelCount);
qFormat.setByteOrder(QAudioFormat::LittleEndian);
if (!info.isFormatSupported((qFormat))) {
qFormat = info.nearestFormat(qFormat);
format.m_bitPerSample = qFormat.sampleSize();
format.m_channelCount = qFormat.channelCount();
format.m_sampleRate = qFormat.sampleRate();
if (qFormat.sampleType() == QAudioFormat::SignedInt)
format.m_signedSample = true;
else
format.m_signedSample = false;
}
#endif
// Create the soundTrack
double samplePerFrame = format.m_sampleRate / fps;