00001 #include <math.h> 00002 #include "MercurySoundDriver.h" 00003 #include "MercurySoundDriverALSA.h" 00004 #include "MercuryLog.h" 00005 00006 void* MercurySoundDriver::TheadFunctCaller(void* x) 00007 { 00008 MercurySoundDriver* y = (MercurySoundDriver*)x; 00009 y->ThreadLoop(); 00010 return 0; 00011 } 00012 00013 MercurySoundDriver& MercurySoundDriver::GetInstance() 00014 { 00015 static MercurySoundDriver* instance = NULL; 00016 if (!instance) 00017 { 00018 instance = new MercurySoundDriverALSA; 00019 instance->Init(); 00020 instance->CreateThread(); 00021 } 00022 return *instance; 00023 } 00024 00025 MercurySoundDriver::MercurySoundDriver() 00026 { 00027 } 00028 00029 MercurySoundDriver::~MercurySoundDriver() 00030 { 00031 Cleanup(); 00032 //halt the thread so we don't try to write to the buffer after it is gone 00033 m_thread.Halt(); 00034 delete(m_buffer); 00035 } 00036 00037 void MercurySoundDriver::CreateThread() 00038 { 00039 #if !defined( NO_THREADS ) 00040 printf("make thread\n"); 00041 m_thread.Create(MercurySoundDriver::TheadFunctCaller, this); 00042 #endif 00043 } 00044 00045 void MercurySoundDriver::ThreadLoop() 00046 { 00047 while (true) 00048 { 00049 ProcessPlayingSounds(); 00050 Sleep(10); 00051 } 00052 } 00053 00054 void MercurySoundDriver::Init() 00055 { 00056 m_rate = 44100; 00057 m_bufferSize = 4096; 00058 m_writeSize = 512; 00059 m_channels = 2; 00060 m_sentFrames = 0; 00061 m_front = &m_buffer; 00062 m_back = &m_buffer2; 00063 m_needData = false; 00064 } 00065 00066 void MercurySoundDriver::ProcessPlayingSounds() 00067 { 00068 m_mutex.Wait(); 00069 if (m_needData) 00070 { 00071 unsigned long samples = m_bufferSize*m_channels; 00072 float mixedData[samples]; 00073 for (unsigned int i = 0; i < samples; ++i) 00074 mixedData[i] = 0; 00075 for (unsigned long i = 0; i < m_playingSounds.size(); ++i) 00076 { 00077 float* data = m_playingSounds[i]->IsPaused()?NULL:m_playingSounds[i]->ReadData(samples); 00078 if (!data) 00079 continue; 00080 for (unsigned long i = 0; i < samples; ++i) 00081 mixedData[i] += data[i]; 00082 delete data; 00083 } 00084 00085 for (unsigned long i = 0; i < samples; ++i) 00086 (*m_back)[i] = lrintf(Clamp(mixedData[i], -1.0f, 1.0f)*32767); 00087 00088 int16_t** tmp = m_front; 00089 m_front = m_back; 00090 m_back = m_front; 00091 00092 m_needData = false; 00093 } 00094 m_mutex.UnLock(); 00095 } 00096 00097 void MercurySoundDriver::AddSound(MercurySoundSourceWAV* sound) 00098 { 00099 m_mutex.Wait(); 00100 m_playingSounds.push_back(sound); 00101 m_mutex.UnLock(); 00102 } 00103 00104 void MercurySoundDriver::RemoveSound(MercurySoundSourceWAV* sound) 00105 { 00106 m_mutex.Wait(); 00107 for (unsigned int i = 0; i < m_playingSounds.size(); ++i) 00108 if (m_playingSounds[i] == sound) 00109 m_playingSounds.remove(i); 00110 // m_playingSounds.erase( m_playingSounds.begin() + i ); 00111 m_mutex.UnLock(); 00112 } 00113 00114 /* 00115 * Copyright (c) 2007 Joshua Allen 00116 * All rights reserved. 00117 * 00118 * Redistribution and use in source and binary forms, with or 00119 * without modification, are permitted provided that the following 00120 * conditions are met: 00121 * - Redistributions of source code must retain the above 00122 * copyright notice, this list of conditions and the following disclaimer. 00123 * - Redistributions in binary form must reproduce the above copyright 00124 * notice, this list of conditions and the following disclaimer in 00125 * the documentation and/or other materials provided with the distribution. 00126 * - Neither the name of the Mercury Engine nor the names of its 00127 * contributors may be used to endorse or promote products derived from 00128 * this software without specific prior written permission. 00129 * 00130 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00131 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00132 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00133 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 00134 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00135 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00136 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00137 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00138 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00139 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00140 */