diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index 832b954..7e5926c 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -226,6 +226,20 @@ E4D13365153767FF0070068C /* KRShaderManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C25A113F4F65A00FF4370 /* KRShaderManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; E4D133661537685A0070068C /* KRShader.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C25A413F4F66F00FF4370 /* KRShader.h */; settings = {ATTRIBUTES = (Public, ); }; }; E4D13367153768610070068C /* KRShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E47C25A813F4F6DD00FF4370 /* KRShader.cpp */; settings = {ATTRIBUTES = (Public, ); }; }; + E4F027C716979CCD00D4427D /* KRAudioManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027C516979CCD00D4427D /* KRAudioManager.cpp */; }; + E4F027C816979CCD00D4427D /* KRAudioManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027C516979CCD00D4427D /* KRAudioManager.cpp */; }; + E4F027C916979CCD00D4427D /* KRAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027C616979CCD00D4427D /* KRAudioManager.h */; }; + E4F027CA16979CCD00D4427D /* KRAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027C616979CCD00D4427D /* KRAudioManager.h */; }; + E4F027CE16979CE200D4427D /* KRAudioSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027CC16979CE200D4427D /* KRAudioSample.cpp */; }; + E4F027CF16979CE200D4427D /* KRAudioSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027CC16979CE200D4427D /* KRAudioSample.cpp */; }; + E4F027D016979CE200D4427D /* KRAudioSample.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027CD16979CE200D4427D /* KRAudioSample.h */; }; + E4F027D116979CE200D4427D /* KRAudioSample.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027CD16979CE200D4427D /* KRAudioSample.h */; }; + E4F027D31697A01300D4427D /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4F027D21697A01300D4427D /* OpenAL.framework */; }; + E4F027D51697A02D00D4427D /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4F027D41697A02D00D4427D /* OpenAL.framework */; }; + E4F027DE1697BFFF00D4427D /* KRAudioBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027DC1697BFFF00D4427D /* KRAudioBuffer.cpp */; }; + E4F027DF1697BFFF00D4427D /* KRAudioBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027DC1697BFFF00D4427D /* KRAudioBuffer.cpp */; }; + E4F027E01697BFFF00D4427D /* KRAudioBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027DD1697BFFF00D4427D /* KRAudioBuffer.h */; }; + E4F027E11697BFFF00D4427D /* KRAudioBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027DD1697BFFF00D4427D /* KRAudioBuffer.h */; }; E4F975321536220900FD60B2 /* KRNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F975311536220900FD60B2 /* KRNode.h */; }; E4F975331536220900FD60B2 /* KRNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F975311536220900FD60B2 /* KRNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; E4F975361536221C00FD60B2 /* KRNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F975351536221C00FD60B2 /* KRNode.cpp */; }; @@ -428,6 +442,14 @@ E4CE184E15FF125700F80870 /* light_point_inside.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = light_point_inside.vsh; path = Shaders/light_point_inside.vsh; sourceTree = ""; }; E4D133B91538F7480070068C /* light_directional.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = light_directional.fsh; path = Shaders/light_directional.fsh; sourceTree = ""; }; E4D133BB1538F7560070068C /* light_directional.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; lineEnding = 0; name = light_directional.vsh; path = Shaders/light_directional.vsh; sourceTree = ""; }; + E4F027C516979CCD00D4427D /* KRAudioManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRAudioManager.cpp; path = Classes/KRAudioManager.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + E4F027C616979CCD00D4427D /* KRAudioManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRAudioManager.h; path = Classes/KRAudioManager.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + E4F027CC16979CE200D4427D /* KRAudioSample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRAudioSample.cpp; path = Classes/KRAudioSample.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + E4F027CD16979CE200D4427D /* KRAudioSample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRAudioSample.h; path = Classes/KRAudioSample.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + E4F027D21697A01300D4427D /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; }; + E4F027D41697A02D00D4427D /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = ../../../../MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; }; + E4F027DC1697BFFF00D4427D /* KRAudioBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRAudioBuffer.cpp; path = Classes/KRAudioBuffer.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + E4F027DD1697BFFF00D4427D /* KRAudioBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRAudioBuffer.h; path = Classes/KRAudioBuffer.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; E4F975311536220900FD60B2 /* KRNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRNode.h; path = Classes/KRNode.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; E4F975351536221C00FD60B2 /* KRNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRNode.cpp; path = Classes/KRNode.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; /* End PBXFileReference section */ @@ -437,6 +459,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E4F027D31697A01300D4427D /* OpenAL.framework in Frameworks */, E4CA10F61638BCAF005D9400 /* Accelerate.framework in Frameworks */, E49101A013C99BF50098455B /* OpenGLES.framework in Frameworks */, E46DBE801512AF4600D59F86 /* Foundation.framework in Frameworks */, @@ -447,6 +470,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E4F027D51697A02D00D4427D /* OpenAL.framework in Frameworks */, E4CA10F81638BCBB005D9400 /* Accelerate.framework in Frameworks */, E4BBBB9C1512A4A900F43B5B /* Foundation.framework in Frameworks */, E4BBBB9D1512A4AC00F43B5B /* CoreData.framework in Frameworks */, @@ -614,7 +638,7 @@ E488399915F92BA300BD66D5 /* Managers */ = { isa = PBXGroup; children = ( - E48B681916977B5600D99917 /* Sound */, + E48B681916977B5600D99917 /* Audio */, E414F9A21694D949000B3D58 /* Unknown */, E416AA96167136FB000F6786 /* AnimationCurve */, E428C2EF166960ED00A16EDF /* Animation */, @@ -727,11 +751,17 @@ name = Physics; sourceTree = ""; }; - E48B681916977B5600D99917 /* Sound */ = { + E48B681916977B5600D99917 /* Audio */ = { isa = PBXGroup; children = ( + E4F027C516979CCD00D4427D /* KRAudioManager.cpp */, + E4F027C616979CCD00D4427D /* KRAudioManager.h */, + E4F027CC16979CE200D4427D /* KRAudioSample.cpp */, + E4F027CD16979CE200D4427D /* KRAudioSample.h */, + E4F027DC1697BFFF00D4427D /* KRAudioBuffer.cpp */, + E4F027DD1697BFFF00D4427D /* KRAudioBuffer.h */, ); - name = Sound; + name = Audio; sourceTree = ""; }; E48C696C15374A1500232E28 /* Scene Graph Nodes */ = { @@ -776,9 +806,10 @@ E491016313C99B9E0098455B /* iOS Frameworks */ = { isa = PBXGroup; children = ( - E4CA10F51638BCAE005D9400 /* Accelerate.framework */, - E491019F13C99BF50098455B /* OpenGLES.framework */, E491016413C99B9E0098455B /* Foundation.framework */, + E4F027D21697A01300D4427D /* OpenAL.framework */, + E491019F13C99BF50098455B /* OpenGLES.framework */, + E4CA10F51638BCAE005D9400 /* Accelerate.framework */, ); name = "iOS Frameworks"; sourceTree = ""; @@ -855,13 +886,14 @@ E4BBBB931512A41500F43B5B /* OSX Frameworks */ = { isa = PBXGroup; children = ( + E4BBBB9A1512A48200F43B5B /* Foundation.framework */, + E46DBE7D1512AD4900D59F86 /* OpenGL.framework */, + E4F027D41697A02D00D4427D /* OpenAL.framework */, E44F37FF1682731700399B5D /* PVRTexLib */, E460292916682BD900261BB9 /* libfbxsdk-2013.3-static.a */, E4CA10F71638BCBB005D9400 /* Accelerate.framework */, E497B95E151BF09600D3DC67 /* SystemConfiguration.framework */, E497B95C151BF05F00D3DC67 /* CoreServices.framework */, - E46DBE7D1512AD4900D59F86 /* OpenGL.framework */, - E4BBBB9A1512A48200F43B5B /* Foundation.framework */, E4BBBB981512A47500F43B5B /* CoreData.framework */, E4BBBB961512A46700F43B5B /* AppKit.framework */, E4BBBB941512A45500F43B5B /* Cocoa.framework */, @@ -947,6 +979,9 @@ E414F9A81694D977000B3D58 /* KRUnknownManager.h in Headers */, E414F9AE1694DA37000B3D58 /* KRUnknown.h in Headers */, E48B68171697794F00D99917 /* KRAudioSource.h in Headers */, + E4F027C916979CCD00D4427D /* KRAudioManager.h in Headers */, + E4F027D016979CE200D4427D /* KRAudioSample.h in Headers */, + E4F027E01697BFFF00D4427D /* KRAudioBuffer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1012,6 +1047,9 @@ E4C454B3167BC04C003586CD /* KRModelSphere.h in Headers */, E44F38251683B23000399B5D /* KRRenderSettings.h in Headers */, E48B68181697794F00D99917 /* KRAudioSource.h in Headers */, + E4F027CA16979CCD00D4427D /* KRAudioManager.h in Headers */, + E4F027D116979CE200D4427D /* KRAudioSample.h in Headers */, + E4F027E11697BFFF00D4427D /* KRAudioBuffer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1153,6 +1191,9 @@ E414F9A61694D977000B3D58 /* KRUnknownManager.cpp in Sources */, E414F9AC1694DA37000B3D58 /* KRUnknown.cpp in Sources */, E48B68151697794F00D99917 /* KRAudioSource.cpp in Sources */, + E4F027C716979CCD00D4427D /* KRAudioManager.cpp in Sources */, + E4F027CE16979CE200D4427D /* KRAudioSample.cpp in Sources */, + E4F027DE1697BFFF00D4427D /* KRAudioBuffer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1218,6 +1259,9 @@ E414F9A71694D977000B3D58 /* KRUnknownManager.cpp in Sources */, E414F9AD1694DA37000B3D58 /* KRUnknown.cpp in Sources */, E48B68161697794F00D99917 /* KRAudioSource.cpp in Sources */, + E4F027C816979CCD00D4427D /* KRAudioManager.cpp in Sources */, + E4F027CF16979CE200D4427D /* KRAudioSample.cpp in Sources */, + E4F027DF1697BFFF00D4427D /* KRAudioBuffer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/KREngine/KREngine/Classes/KRAudioBuffer.cpp b/KREngine/KREngine/Classes/KRAudioBuffer.cpp new file mode 100644 index 0000000..11a5ab3 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAudioBuffer.cpp @@ -0,0 +1,45 @@ +// +// KRAudioBuffer.cpp +// KREngine +// +// Created by Kearwood Gilbert on 2013-01-04. +// Copyright (c) 2013 Kearwood Software. All rights reserved. +// + +#include "KRAudioBuffer.h" +#include "KRAudioManager.h" + + +KRAudioBuffer::KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, ALenum dataFormat, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *)) +{ + m_bufferID = 0; + m_pSoundManager = manager; + m_dataFormat = dataFormat; + m_frameCount = frameCount; + m_frameRate = frameRate; + m_bytesPerFrame = bytesPerFrame; + m_pData = NULL; + + m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame); + fn_populate(sound, index, m_pData->getStart()); + + m_pSoundManager->makeCurrentContext(); + alGenBuffers(1, &m_bufferID); + alBufferData(m_bufferID, m_dataFormat, m_pData->getStart(), m_frameCount * m_bytesPerFrame, m_frameRate); +} + +KRAudioBuffer::~KRAudioBuffer() +{ + if(m_bufferID) { + alDeleteBuffers(1, &m_bufferID); + m_bufferID = 0; + } + + m_pSoundManager->recycleBufferData(m_pData); +} + + +unsigned int KRAudioBuffer::getBufferID() +{ + return m_bufferID; +} diff --git a/KREngine/KREngine/Classes/KRAudioBuffer.h b/KREngine/KREngine/Classes/KRAudioBuffer.h new file mode 100644 index 0000000..7844c12 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAudioBuffer.h @@ -0,0 +1,38 @@ +// +// KRAudioBuffer.h +// KREngine +// +// Created by Kearwood Gilbert on 2013-01-04. +// Copyright (c) 2013 Kearwood Software. All rights reserved. +// + +#ifndef KRAUDIO_BUFFER_H +#define KRAUDIO_BUFFER_H + +#include "KREngine-common.h" +#include "KRDataBlock.h" + +class KRAudioManager; +class KRAudioSample; + +class KRAudioBuffer +{ +public: + KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, ALenum dataFormat, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *)); + ~KRAudioBuffer(); + + unsigned int getBufferID(); +private: + KRAudioManager *m_pSoundManager; + + + ALenum m_dataFormat; + int m_frameCount; + int m_frameRate; + int m_bytesPerFrame; + KRDataBlock *m_pData; + + unsigned int m_bufferID; +}; + +#endif /* defined(KRAUDIO_BUFFER_H) */ diff --git a/KREngine/KREngine/Classes/KRAudioManager.cpp b/KREngine/KREngine/Classes/KRAudioManager.cpp new file mode 100644 index 0000000..6d2dfa6 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAudioManager.cpp @@ -0,0 +1,193 @@ +// +// FileManager.cpp +// KREngine +// +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#include "KRAudioManager.h" +#include "KREngine-common.h" +#include "KRDataBlock.h" + +OSStatus alcASASetListenerProc(const ALuint property, ALvoid *data, ALuint dataSize); +ALvoid alcMacOSXRenderingQualityProc(const ALint value); + +KRAudioManager::KRAudioManager(KRContext &context) : KRContextObject(context) +{ + // ----- Initialize OpenAL ----- + m_alDevice = alcOpenDevice(NULL); + m_alContext=alcCreateContext(m_alDevice,NULL); + alcMakeContextCurrent(m_alContext); + + // ----- Configure listener ----- + alDistanceModel(AL_EXPONENT_DISTANCE); + alcMacOSXRenderingQualityProc(ALC_IPHONE_SPATIAL_RENDERING_QUALITY_HEADPHONES); + UInt32 setting = 1; + alcASASetListenerProc(ALC_ASA_REVERB_ON, &setting, sizeof(setting)); + ALfloat global_reverb_level = -5.0f; + alcASASetListenerProc(ALC_ASA_REVERB_GLOBAL_LEVEL, &global_reverb_level, sizeof(global_reverb_level)); + + setting = ALC_ASA_REVERB_ROOM_TYPE_MediumHall2; + alcASASetListenerProc(ALC_ASA_REVERB_ROOM_TYPE, &setting, sizeof(setting)); + + + ALfloat global_reverb_eq_gain = 0.0f; + alcASASetListenerProc(ALC_ASA_REVERB_EQ_GAIN, &global_reverb_eq_gain, sizeof(global_reverb_eq_gain)); + + ALfloat global_reverb_eq_bandwidth = 0.0f; + alcASASetListenerProc(ALC_ASA_REVERB_EQ_BANDWITH, &global_reverb_eq_bandwidth, sizeof(global_reverb_eq_bandwidth)); + + ALfloat global_reverb_eq_freq = 0.0f; + alcASASetListenerProc(ALC_ASA_REVERB_EQ_FREQ, &global_reverb_eq_freq, sizeof(global_reverb_eq_freq)); +} + +KRAudioManager::~KRAudioManager() +{ + for(map::iterator name_itr=m_sounds.begin(); name_itr != m_sounds.end(); name_itr++) { + delete (*name_itr).second; + } + + if(m_alContext) { + alcDestroyContext(m_alContext); + m_alContext = 0; + } + if(m_alDevice) { + alcCloseDevice(m_alDevice); + m_alDevice = 0; + } + + for(std::vector::iterator itr = m_bufferPoolIdle.begin(); itr != m_bufferPoolIdle.end(); itr++) { + delete *itr; + } +} + +void KRAudioManager::makeCurrentContext() +{ + alcMakeContextCurrent(m_alContext); +} + +void KRAudioManager::setViewMatrix(const KRMat4 &viewMatrix) +{ + makeCurrentContext(); + KRMat4 invView = viewMatrix; + invView.invert(); + + KRVector3 player_position = KRMat4::Dot(invView, KRVector3(0.0, 0.0, 0.0)); + KRVector3 vectorForward = KRMat4::Dot(invView, KRVector3(0.0, 0.0, -1.0)) - player_position; + KRVector3 vectorUp = KRMat4::Dot(invView, KRVector3(0.0, 1.0, 0.0)) - player_position; + + vectorUp.normalize(); + vectorForward.normalize(); + alcMakeContextCurrent(m_alContext); + alListener3f(AL_POSITION, player_position.x, player_position.y, player_position.z); + ALfloat orientation[] = {vectorForward.x, vectorForward.y, vectorForward.z, vectorUp.x, vectorUp.y, vectorUp.z}; + alListenerfv(AL_ORIENTATION, orientation); +} + +void KRAudioManager::add(KRAudioSample *sound) +{ + std::string lower_name = sound->getName(); + std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower); + + map::iterator name_itr = m_sounds.find(lower_name); + if(name_itr != m_sounds.end()) { + delete (*name_itr).second; + (*name_itr).second = sound; + } else { + m_sounds[lower_name] = sound; + } +} + +KRAudioSample *KRAudioManager::load(const std::string &name, const std::string &extension, KRDataBlock *data) +{ + KRAudioSample *Sound = new KRAudioSample(getContext(), name, extension, data); + if(Sound) add(Sound); + return Sound; +} + +KRAudioSample *KRAudioManager::get(const std::string &name) +{ + std::string lower_name = name; + std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower); + return m_sounds[lower_name]; +} + +KRDataBlock *KRAudioManager::getBufferData(int size) +{ + KRDataBlock *data; + // Note: We only store and recycle buffers with a size of CIRCA_AUDIO_MAX_BUFFER_SIZE + if(size == KRENGINE_AUDIO_MAX_BUFFER_SIZE && m_bufferPoolIdle.size() > 0) { + // Recycle a buffer from the pool + data = m_bufferPoolIdle.back(); + m_bufferPoolIdle.pop_back(); + } else { + data = new KRDataBlock(); + data->expand(size); + } + + return data; + +} + +void KRAudioManager::recycleBufferData(KRDataBlock *data) +{ + if(data != NULL) { + if(data->getSize() == KRENGINE_AUDIO_MAX_BUFFER_SIZE && m_bufferPoolIdle.size() < KRENGINE_AUDIO_MAX_POOL_SIZE) { + m_bufferPoolIdle.push_back(data); + } else { + delete data; + } + } +} + +OSStatus alcASASetListenerProc(const ALuint property, ALvoid *data, ALuint dataSize) +{ + OSStatus err = noErr; + static alcASASetListenerProcPtr proc = NULL; + + if (proc == NULL) { + proc = (alcASASetListenerProcPtr) alcGetProcAddress(NULL, "alcASASetListener"); + } + + if (proc) + err = proc(property, data, dataSize); + return (err); +} + +ALvoid alcMacOSXRenderingQualityProc(const ALint value) +{ + static alcMacOSXRenderingQualityProcPtr proc = NULL; + + if (proc == NULL) { + proc = (alcMacOSXRenderingQualityProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXRenderingQuality"); + } + + if (proc) + proc(value); + + return; +} diff --git a/KREngine/KREngine/Classes/KRAudioManager.h b/KREngine/KREngine/Classes/KRAudioManager.h new file mode 100644 index 0000000..e8f4a61 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAudioManager.h @@ -0,0 +1,81 @@ +// +// FileManager.h +// KREngine +// +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#ifndef KRAUDIO_MANAGER_H +#define KRAUDIO_MANAGER_H + +#import "KREngine-common.h" + +#include "KRAudioSample.h" +#include "KRContextObject.h" +#include "KRDataBlock.h" +#include "KRmat4.h" + +#include +#include +#include + +using std::map; +using std::set; + +const int KRENGINE_AUDIO_MAX_POOL_SIZE = 32; +const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 64*1024; +const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3; + +class KRAudioManager : public KRContextObject { +public: + KRAudioManager(KRContext &context); + virtual ~KRAudioManager(); + + void add(KRAudioSample *Sound); + + KRAudioSample *load(const std::string &name, const std::string &extension, KRDataBlock *data); + KRAudioSample *get(const std::string &name); + + void setViewMatrix(const KRMat4 &viewMatrix); + + + void makeCurrentContext(); + + KRDataBlock *getBufferData(int size); + void recycleBufferData(KRDataBlock *data); + +private: + map m_sounds; + + std::vector m_bufferPoolIdle; + + ALCcontext* m_alContext; + ALCdevice* m_alDevice; + +}; + +#endif /* defined(KRAUDIO_MANAGER_H) */ diff --git a/KREngine/KREngine/Classes/KRAudioSample.cpp b/KREngine/KREngine/Classes/KRAudioSample.cpp new file mode 100644 index 0000000..c14a449 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAudioSample.cpp @@ -0,0 +1,229 @@ +// +// KRAudioSample.cpp +// KREngine +// +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#include "KRAudioSample.h" +#include "KRAudioManager.h" +#include "KRDataBlock.h" +#include "KRAudioBuffer.h" +#include "KRContext.h" + +KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name) +{ + m_pData = new KRDataBlock(); + m_extension = extension; + + m_audio_file_id = 0; + m_fileRef = NULL; + m_totalFrames = 0; + m_bytesPerFrame = 0; + m_frameRate = 0; + m_bufferCount = 0; + + openFile(); +} + +KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name) +{ + m_pData = data; + m_extension = extension; + + m_audio_file_id = 0; + m_fileRef = NULL; + m_totalFrames = 0; + m_bytesPerFrame = 0; + m_frameRate = 0; + m_bufferCount = 0; + + openFile(); + +} + +KRAudioSample::~KRAudioSample() +{ + closeFile(); + delete m_pData; +} + + +OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc + void * inClientData, + SInt64 inPosition, + UInt32 requestCount, + void * buffer, + UInt32 * actualCount) +{ + KRAudioSample *sound = (KRAudioSample *)inClientData; + UInt32 max_count = sound->m_pData->getSize() - inPosition; + *actualCount = requestCount < max_count ? requestCount : max_count; + memcpy(buffer, (unsigned char *)sound->m_pData->getStart() + inPosition, *actualCount); + return noErr; +} + +SInt64 KRAudioSample::GetSizeProc( // AudioFile_GetSizeProc + void * inClientData) +{ + KRAudioSample *sound = (KRAudioSample *)inClientData; + return sound->m_pData->getSize(); +} + +OSStatus KRAudioSample::SetSizeProc( // AudioFile_SetSizeProc + void * inClientData, + SInt64 inSize) +{ + return -1; // Writing not supported +} + +OSStatus KRAudioSample::WriteProc( // AudioFile_WriteProc + void * inClientData, + SInt64 inPosition, + UInt32 requestCount, + const void *buffer, + UInt32 * actualCount) +{ + return -1; // Writing not supported +} + + +void KRAudioSample::openFile() +{ + // AudioFileInitializeWithCallbacks + if(m_fileRef == NULL) { + // Temp variables + UInt32 propertySize; + + // ---- Open audio file ---- +// ExtAudioFileOpenURL((CFURLRef)m_soundURL, &_fileRef); + + + assert(AudioFileOpenWithCallbacks((void *)this, ReadProc, WriteProc, GetSizeProc, SetSizeProc, 0, &m_audio_file_id) == noErr); + assert(ExtAudioFileWrapAudioFileID(m_audio_file_id, false, &m_fileRef) == noErr); + + + // ---- Get file format information ---- + AudioStreamBasicDescription inputFormat; + propertySize = sizeof(inputFormat); + ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileDataFormat, &propertySize, &inputFormat); + + // ---- Set up output format ---- + AudioStreamBasicDescription outputFormat; + // Set the client format to 16 bit signed integer (native-endian) data + // Maintain the channel count and sample rate of the original source format + outputFormat.mSampleRate = inputFormat.mSampleRate; + outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame; + outputFormat.mFormatID = kAudioFormatLinearPCM; + outputFormat.mBytesPerPacket = 2 * outputFormat.mChannelsPerFrame; + outputFormat.mFramesPerPacket = 1; + outputFormat.mBytesPerFrame = 2 * outputFormat.mChannelsPerFrame; + outputFormat.mBitsPerChannel = 16; + outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; + ExtAudioFileSetProperty(m_fileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat); + + // ---- Get the buffer size and format parameters ---- + propertySize = sizeof(m_totalFrames); + ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileLengthFrames, &propertySize, &m_totalFrames); + + m_bytesPerFrame = outputFormat.mBytesPerFrame; + m_frameRate = outputFormat.mSampleRate; + + int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame; + m_bufferCount = (m_totalFrames+maxFramesPerBuffer-1)/maxFramesPerBuffer; // CEIL(_totalFrames / maxFramesPerBuffer) + + m_dataFormat = (outputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; + m_channelsPerFrame = outputFormat.mChannelsPerFrame; + } +} + +void KRAudioSample::closeFile() +{ + if(m_fileRef) { + ExtAudioFileDispose(m_fileRef); + m_fileRef = NULL; + } + + if(m_audio_file_id) { + AudioFileClose(m_audio_file_id); + m_audio_file_id = 0; + } +} + +std::string KRAudioSample::getExtension() +{ + return m_extension; +} + +bool KRAudioSample::save(KRDataBlock &data) +{ + data.append(*m_pData); + return true; +} + +float KRAudioSample::getDuration() +{ + openFile(); + return (float)m_totalFrames / (float)m_frameRate; +} + +int KRAudioSample::getBufferCount() +{ + openFile(); + return m_bufferCount; +} + +void KRAudioSample::PopulateBuffer(KRAudioSample *sound, int index, void *data) +{ + int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / sound->m_bytesPerFrame; + int startFrame = index * maxFramesPerBuffer; + UInt32 frameCount = KRMIN(sound->m_totalFrames - startFrame, maxFramesPerBuffer); + + + AudioBufferList outputBufferInfo; + outputBufferInfo.mNumberBuffers = 1; + outputBufferInfo.mBuffers[0].mDataByteSize = frameCount * sound->m_bytesPerFrame; + outputBufferInfo.mBuffers[0].mNumberChannels = sound->m_channelsPerFrame; + outputBufferInfo.mBuffers[0].mData = data; + + // Read the data into an AudioBufferList + ExtAudioFileSeek(sound->m_fileRef, startFrame); + ExtAudioFileRead(sound->m_fileRef, (UInt32*)&frameCount, &outputBufferInfo); +} + +KRAudioBuffer *KRAudioSample::getBuffer(int index) +{ + openFile(); + + KRAudioBuffer *buffer = new KRAudioBuffer(getContext().getAudioManager(), this, index, m_dataFormat, m_totalFrames, m_frameRate, m_bytesPerFrame, PopulateBuffer); + + if(m_bufferCount == 1) { +// [self closeFile]; // We don't need to hold on to a file handle if not streaming + } + return buffer; +} + diff --git a/KREngine/KREngine/Classes/KRAudioSample.h b/KREngine/KREngine/Classes/KRAudioSample.h new file mode 100644 index 0000000..48f86fa --- /dev/null +++ b/KREngine/KREngine/Classes/KRAudioSample.h @@ -0,0 +1,103 @@ +// +// KRAudioSample.h +// KREngine +// +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#ifndef KRAUDIOSAMPLE_H +#define KRAUDIOSAMPLE_H + +#import "KREngine-common.h" +#import "KRContextObject.h" +#import "KRDataBlock.h" +#import "KRResource.h" +#import + +class KRAudioBuffer; + +class KRAudioSample : public KRResource { + +public: + KRAudioSample(KRContext &context, std::string name, std::string extension); + KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data); + virtual ~KRAudioSample(); + + virtual std::string getExtension(); + + virtual bool save(KRDataBlock &data); + + float getDuration(); + KRAudioBuffer *getBuffer(int index); + int getBufferCount(); + +private: + + std::string m_extension; + KRDataBlock *m_pData; + + AudioFileID m_audio_file_id; + ExtAudioFileRef m_fileRef; + + int m_bufferCount; + + SInt64 m_totalFrames; + int m_frameRate; + int m_bytesPerFrame; + int m_channelsPerFrame; + ALenum m_dataFormat; + + void openFile(); + void closeFile(); + + static OSStatus ReadProc( // AudioFile_ReadProc + void * inClientData, + SInt64 inPosition, + UInt32 requestCount, + void * buffer, + UInt32 * actualCount); + + static OSStatus WriteProc( // AudioFile_WriteProc + void * inClientData, + SInt64 inPosition, + UInt32 requestCount, + const void *buffer, + UInt32 * actualCount); + + static SInt64 GetSizeProc( // AudioFile_GetSizeProc + void * inClientData); + + + static OSStatus SetSizeProc( // AudioFile_SetSizeProc + void * inClientData, + SInt64 inSize); + + + static void PopulateBuffer(KRAudioSample *sound, int index, void *data); +}; + +#endif /* defined(KRAUDIOSAMPLE_H) */ diff --git a/KREngine/KREngine/Classes/KRAudioSource.cpp b/KREngine/KREngine/Classes/KRAudioSource.cpp index 401c58a..7fd1a12 100644 --- a/KREngine/KREngine/Classes/KRAudioSource.cpp +++ b/KREngine/KREngine/Classes/KRAudioSource.cpp @@ -31,14 +31,33 @@ #include "KRAudioSource.h" #include "KRContext.h" +#include "KRAudioManager.h" +#include "KRAudioSample.h" +#include "KRAudioBuffer.h" KRAudioSource::KRAudioSource(KRScene &scene, std::string name) : KRNode(scene, name) { - + m_playing = false; + m_is3d = true; + m_isPrimed = false; + m_audioFile = NULL; + m_sourceID = 0; + m_gain = 1.0f; + m_pitch = 1.0f; + m_looping = false; } KRAudioSource::~KRAudioSource() { + if(m_sourceID) { + getContext().getAudioManager()->makeCurrentContext(); + alDeleteSources(1, &m_sourceID); + m_sourceID = 0; + } + while(m_audioBuffers.size()) { + delete m_audioBuffers.front(); + m_audioBuffers.pop(); + } } std::string KRAudioSource::getElementName() { @@ -48,16 +67,77 @@ std::string KRAudioSource::getElementName() { tinyxml2::XMLElement *KRAudioSource::saveXML( tinyxml2::XMLNode *parent) { tinyxml2::XMLElement *e = KRNode::saveXML(parent); - e->SetAttribute("sound", m_sound.c_str()); + e->SetAttribute("sample", m_audio_sample_name.c_str()); + e->SetAttribute("gain", m_gain); + e->SetAttribute("pitch", m_pitch); + e->SetAttribute("looping", m_looping ? "true" : "false"); return e; } void KRAudioSource::loadXML(tinyxml2::XMLElement *e) { - m_sound = e->Attribute("sound"); + m_audio_sample_name = e->Attribute("sample"); + + float gain = 1.0f; + if(e->QueryFloatAttribute("gain", &gain) != tinyxml2::XML_SUCCESS) { + gain = 1.0f; + } + setGain(gain); + + float pitch = 1.0f; + if(e->QueryFloatAttribute("pitch", &pitch) != tinyxml2::XML_SUCCESS) { + pitch = 1.0f; + } + setPitch(m_pitch); + + bool looping = false; + if(e->QueryBoolAttribute("looping", &looping) != tinyxml2::XML_SUCCESS) { + looping = false; + } + setLooping(looping); + KRNode::loadXML(e); } +void KRAudioSource::prime() +{ + if(!m_isPrimed) { + if(m_audioFile == NULL && m_audio_sample_name.size() != 0) { + m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name); + } + if(m_audioFile) { + getContext().getAudioManager()->makeCurrentContext(); + + // Initialize audio source + m_sourceID = 0; + alGenSources(1, &m_sourceID); + + // Prime the buffer queue + m_nextBufferIndex = 0; + for(int i=0; i < KRENGINE_AUDIO_BUFFERS_PER_SOURCE; i++) { + queueBuffer(); + } + + //alSourcei(_sourceID, AL_BUFFER, firstBuffer.bufferID); + alSourcef(m_sourceID, AL_PITCH, m_pitch); + alSourcei(m_sourceID, AL_LOOPING, m_looping && m_audioFile->getBufferCount() == 1); + alSourcef(m_sourceID, AL_GAIN, m_gain); + + m_isPrimed = true; + } + } +} + +void KRAudioSource::queueBuffer() +{ + KRAudioBuffer *buffer = m_audioFile->getBuffer(m_nextBufferIndex); + m_audioBuffers.push(buffer); + ALuint buffer_ids[1]; + buffer_ids[0] = buffer->getBufferID(); + alSourceQueueBuffers(m_sourceID, 1, buffer_ids); + + m_nextBufferIndex = (m_nextBufferIndex + 1) % m_audioFile->getBufferCount(); +} void KRAudioSource::render(KRCamera *pCamera, std::vector &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { @@ -99,9 +179,74 @@ void KRAudioSource::render(KRCamera *pCamera, std::vector &lights, co } } +void KRAudioSource::setGain(float gain) +{ + m_gain = gain; + if(m_isPrimed) { + getContext().getAudioManager()->makeCurrentContext(); + alSourcef(m_sourceID, AL_GAIN, m_gain); + } +} + +float KRAudioSource::getGain() +{ + return m_gain; +} + +void KRAudioSource::setPitch(float pitch) +{ + m_pitch = pitch; + if(m_isPrimed ) { + getContext().getAudioManager()->makeCurrentContext(); + alSourcef(m_sourceID, AL_PITCH, m_pitch); + + } +} + +void KRAudioSource::setLooping(bool looping) +{ + m_looping = looping; + // Audio source must be stopped and re-started for loop mode changes to take effect +} + +bool KRAudioSource::getLooping() +{ + return m_looping; +} + +bool KRAudioSource::hasPhysics() +{ + return true; +} + +void KRAudioSource::physicsUpdate(float deltaTime) +{ + if(m_isPrimed && m_playing) { + getContext().getAudioManager()->makeCurrentContext(); + ALint processed_count = 0; + alGetSourcei(m_sourceID, AL_BUFFERS_PROCESSED, &processed_count); + while(processed_count-- > 0) { + ALuint finished_buffer = 0; + alSourceUnqueueBuffers(m_sourceID, 1, &finished_buffer); + delete m_audioBuffers.front(); + m_audioBuffers.pop(); + queueBuffer(); + } + + ALint val; + // Make sure the source is still playing, and restart it if needed. + alGetSourcei(m_sourceID, AL_SOURCE_STATE, &val); + if(val != AL_PLAYING) alSourcePlay(m_sourceID); + } +} + void KRAudioSource::play() { - + prime(); + getContext().getAudioManager()->makeCurrentContext(); + + alSourcePlay(m_sourceID); + m_playing = true; } void KRAudioSource::stop() @@ -111,16 +256,16 @@ void KRAudioSource::stop() bool KRAudioSource::isPlaying() { - return false; + return m_playing; } -void KRAudioSource::setSound(const std::string &sound_name) +void KRAudioSource::setSample(const std::string &sound_name) { - m_sound = sound_name; + m_audio_sample_name = sound_name; } -std::string KRAudioSource::getSound() +std::string KRAudioSource::getSample() { - return m_sound; + return m_audio_sample_name; } diff --git a/KREngine/KREngine/Classes/KRAudioSource.h b/KREngine/KREngine/Classes/KRAudioSource.h index 73b9306..3c8b20a 100644 --- a/KREngine/KREngine/Classes/KRAudioSource.h +++ b/KREngine/KREngine/Classes/KRAudioSource.h @@ -36,6 +36,11 @@ #import "KRNode.h" #import "KRTexture.h" +#include + +class KRAudioSample; +class KRAudioBuffer; + class KRAudioSource : public KRNode { public: KRAudioSource(KRScene &scene, std::string name); @@ -43,16 +48,42 @@ public: virtual std::string getElementName(); virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual void loadXML(tinyxml2::XMLElement *e); + virtual bool hasPhysics(); + virtual void physicsUpdate(float deltaTime); void render(KRCamera *pCamera, std::vector &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); void play(); void stop(); bool isPlaying(); - void setSound(const std::string &sound_name); - std::string getSound(); + + void setSample(const std::string &sound_name); + std::string getSample(); + + float getGain(); + void setGain(float gain); + + float getPitch(); + void setPitch(float pitch); + + bool getLooping(); + void setLooping(bool looping); private: - std::string m_sound; + std::string m_audio_sample_name; + + KRAudioSample *m_audioFile; + unsigned int m_sourceID; + float m_gain; + float m_pitch; + bool m_looping; + std::queue m_audioBuffers; + int m_nextBufferIndex; + bool m_playing; + bool m_is3d; + bool m_isPrimed; + + void prime(); + void queueBuffer(); }; #endif /* defined(KRAUDIOSOURCE_H) */ diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 62dd765..4174218 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -72,6 +72,7 @@ void KRCamera::renderFrame(float deltaTime) KRMat4 viewMatrix = KRMat4::Invert(getModelMatrix()); + getContext().getAudioManager()->setViewMatrix(viewMatrix); // FINDME, TODO - Should we support de-coupling the audio listener location from the camera? GLint defaultFBO; GLDEBUG(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO)); diff --git a/KREngine/KREngine/Classes/KRContext.cpp b/KREngine/KREngine/Classes/KRContext.cpp index 79df3de..3f87bb6 100644 --- a/KREngine/KREngine/Classes/KRContext.cpp +++ b/KREngine/KREngine/Classes/KRContext.cpp @@ -35,6 +35,7 @@ KRContext::KRContext() { m_pSceneManager = new KRSceneManager(*this); m_pAnimationManager = new KRAnimationManager(*this); m_pAnimationCurveManager = new KRAnimationCurveManager(*this); + m_pSoundManager = new KRAudioManager(*this); m_pUnknownManager = new KRUnknownManager(*this); m_bDetectedExtensions = false; m_current_frame = 0; @@ -77,6 +78,11 @@ KRContext::~KRContext() { delete m_pAnimationCurveManager; m_pAnimationCurveManager = NULL; } + + if(m_pSoundManager) { + delete m_pSoundManager; + m_pSoundManager = NULL; + } if(m_pUnknownManager) { delete m_pUnknownManager; @@ -114,6 +120,9 @@ KRAnimationManager *KRContext::getAnimationManager() { KRAnimationCurveManager *KRContext::getAnimationCurveManager() { return m_pAnimationCurveManager; } +KRAudioManager *KRContext::getAudioManager() { + return m_pSoundManager; +} KRUnknownManager *KRContext::getUnknownManager() { return m_pUnknownManager; } @@ -144,12 +153,16 @@ void KRContext::loadResource(const std::string &file_name, KRDataBlock *data) { m_pShaderManager->loadFragmentShader(name.c_str(), data); } else if(extension.compare("mtl") == 0) { m_pMaterialManager->load(name.c_str(), data); + } else if(extension.compare("mp3") == 0) { + m_pSoundManager->load(name.c_str(), extension, data); + } else if(extension.compare("wav") == 0) { + m_pSoundManager->load(name.c_str(), extension, data); + } else if(extension.compare("aac") == 0) { + m_pSoundManager->load(name.c_str(), extension, data); } else { m_pUnknownManager->load(name, extension, data); delete data; } - - } void KRContext::loadResource(std::string path) { diff --git a/KREngine/KREngine/Classes/KRContext.h b/KREngine/KREngine/Classes/KRContext.h index e8eca21..63e4cd7 100644 --- a/KREngine/KREngine/Classes/KRContext.h +++ b/KREngine/KREngine/Classes/KRContext.h @@ -18,6 +18,7 @@ #import "KRModelManager.h" #import "KRAnimationManager.h" #import "KRAnimationCurveManager.h" +#import "KRAudioManager.h" #import "KRUnknownManager.h" class KRContext { @@ -48,6 +49,7 @@ public: KRModelManager *getModelManager(); KRAnimationManager *getAnimationManager(); KRAnimationCurveManager *getAnimationCurveManager(); + KRAudioManager *getAudioManager(); KRUnknownManager *getUnknownManager(); KRCamera *createCamera(int width, int height); @@ -76,6 +78,7 @@ private: KRModelManager *m_pModelManager; KRAnimationManager *m_pAnimationManager; KRAnimationCurveManager *m_pAnimationCurveManager; + KRAudioManager *m_pSoundManager; KRUnknownManager *m_pUnknownManager; void detectExtensions(); diff --git a/KREngine/KREngine/Classes/KREngine-common.h b/KREngine/KREngine/Classes/KREngine-common.h index 46868e1..2344796 100644 --- a/KREngine/KREngine/Classes/KREngine-common.h +++ b/KREngine/KREngine/Classes/KREngine-common.h @@ -51,6 +51,12 @@ float const D2R = PI * 2 / 360; #endif +#import +#import +#import +#import +#import +#import #endif @@ -65,6 +71,8 @@ fprintf(stderr, "Error at line number %d, in file %s. glGetError() returned %i f } \ } +#define KRMIN(x,y) ((x) < (y) ? (x) : (y)) +#define KRMAX(x,y) ((x) > (y) ? (x) : (y)) #include "KRVector3.h" #include "KRVector2.h" \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRParticleSystemNewtonian.cpp b/KREngine/KREngine/Classes/KRParticleSystemNewtonian.cpp index ed11915..b4d781c 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemNewtonian.cpp +++ b/KREngine/KREngine/Classes/KRParticleSystemNewtonian.cpp @@ -49,6 +49,11 @@ void KRParticleSystemNewtonian::physicsUpdate(float deltaTime) m_particlesAbsoluteTime += deltaTime; } +bool KRParticleSystemNewtonian::hasPhysics() +{ + return true; +} + void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { diff --git a/KREngine/KREngine/Classes/KRParticleSystemNewtonian.h b/KREngine/KREngine/Classes/KRParticleSystemNewtonian.h index 8fda770..b4a4ab3 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemNewtonian.h +++ b/KREngine/KREngine/Classes/KRParticleSystemNewtonian.h @@ -27,6 +27,7 @@ public: virtual void physicsUpdate(float deltaTime); + virtual bool hasPhysics(); private: float m_particlesAbsoluteTime; }; diff --git a/KREngine/KREngine/Classes/KRSceneManager.cpp b/KREngine/KREngine/Classes/KRSceneManager.cpp index e3d6cc9..bf9e321 100644 --- a/KREngine/KREngine/Classes/KRSceneManager.cpp +++ b/KREngine/KREngine/Classes/KRSceneManager.cpp @@ -53,8 +53,12 @@ KRScene *KRSceneManager::getScene(const char *szName) { } KRScene *KRSceneManager::getFirstScene() { - static std::map::iterator Scene_itr = m_scenes.begin(); - return (*Scene_itr).second; + static std::map::iterator scene_itr = m_scenes.begin(); + if(scene_itr == m_scenes.end()) { + return NULL; + } else { + return (*scene_itr).second; + } } std::map KRSceneManager::getScenes() { diff --git a/KREngine/KREngine/Classes/KRUnknown.cpp b/KREngine/KREngine/Classes/KRUnknown.cpp index 79558fd..a4d2ec4 100644 --- a/KREngine/KREngine/Classes/KRUnknown.cpp +++ b/KREngine/KREngine/Classes/KRUnknown.cpp @@ -2,8 +2,31 @@ // KRUnknown.cpp // KREngine // -// Created by Kearwood Gilbert on 2013-01-02. -// Copyright (c) 2013 Kearwood Software. All rights reserved. +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. // #include "KRUnknown.h" diff --git a/KREngine/KREngine/Classes/KRUnknown.h b/KREngine/KREngine/Classes/KRUnknown.h index e344177..3d9d7b0 100644 --- a/KREngine/KREngine/Classes/KRUnknown.h +++ b/KREngine/KREngine/Classes/KRUnknown.h @@ -2,8 +2,31 @@ // KRUnknown.h // KREngine // -// Created by Kearwood Gilbert on 2013-01-02. -// Copyright (c) 2013 Kearwood Software. All rights reserved. +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. // #ifndef KRUNKNOWN_H diff --git a/KREngine/KREngine/Classes/KRUnknownManager.cpp b/KREngine/KREngine/Classes/KRUnknownManager.cpp index 07bda9d..2b8dd79 100644 --- a/KREngine/KREngine/Classes/KRUnknownManager.cpp +++ b/KREngine/KREngine/Classes/KRUnknownManager.cpp @@ -2,8 +2,31 @@ // FileManager.cpp // KREngine // -// Created by Kearwood Gilbert on 2013-01-02. -// Copyright (c) 2013 Kearwood Software. All rights reserved. +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. // #include "KRUnknownManager.h" diff --git a/KREngine/KREngine/Classes/KRUnknownManager.h b/KREngine/KREngine/Classes/KRUnknownManager.h index dc2d48a..fbb0dfd 100644 --- a/KREngine/KREngine/Classes/KRUnknownManager.h +++ b/KREngine/KREngine/Classes/KRUnknownManager.h @@ -2,8 +2,31 @@ // FileManager.h // KREngine // -// Created by Kearwood Gilbert on 2013-01-02. -// Copyright (c) 2013 Kearwood Software. All rights reserved. +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. // #ifndef KRUNKNOWN_MANAGER_H