Skip to content

Commit

Permalink
Add support for multiple sound effects
Browse files Browse the repository at this point in the history
  • Loading branch information
justindriggers committed Mar 9, 2023
1 parent 6cc3456 commit e7e58b0
Show file tree
Hide file tree
Showing 25 changed files with 199 additions and 37 deletions.
1 change: 1 addition & 0 deletions alfredo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_executable(alfredo
src/main.mm
src/appkit/AlfredoApplicationDelegate.mm
src/metalkit/AlfredoViewDelegate.mm
src/platform/MacAudioEngineFileLoader.mm
src/platform/MacInputManager.mm
src/platform/MacLifecycleManager.mm
src/platform/MacLogger.mm
Expand Down
5 changes: 4 additions & 1 deletion alfredo/src/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import <Engine.h>

#import "appkit/AlfredoApplicationDelegate.h"
#import "platform/MacAudioEngineFileLoader.h"
#import "platform/MacInputManager.h"
#import "platform/MacLifecycleManager.h"
#import "platform/MacLogger.h"
Expand All @@ -23,8 +24,10 @@ int main(int argc, const char *argv[]) {

[app run];

auto audioFileLoader = std::make_unique<MacAudioEngineFileLoader>();

auto logger = std::make_shared<MacLogger>();
auto audioManager = std::make_shared<audio::AudioEngineAudioManager>();
auto audioManager = std::make_shared<audio::AudioEngineAudioManager>(std::move(audioFileLoader));
auto inputManager = std::make_shared<MacInputManager>();
auto lifecycleManager = std::make_shared<MacLifecycleManager>();
auto renderer = std::shared_ptr<Renderer>(appDelegate.metalRenderer);
Expand Down
14 changes: 14 additions & 0 deletions alfredo/src/platform/MacAudioEngineFileLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <AudioEngineFileLoader.h>

#import <Foundation/NSURL.h>

namespace linguine::alfredo {

class MacAudioEngineFileLoader : public audio::AudioEngineFileLoader {
public:
NSURL* getUrlForEffect(EffectType effectType) override;
};

} // namespace linguine::alfredo
25 changes: 25 additions & 0 deletions alfredo/src/platform/MacAudioEngineFileLoader.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "MacAudioEngineFileLoader.h"

namespace linguine::alfredo {

NSURL* MacAudioEngineFileLoader::getUrlForEffect(EffectType effectType) {
NSString* path;

switch (effectType) {
case Pop:
path = @"Balloon Pop 1.wav";
break;
case Select:
path = @"Select 1.wav";
break;
}

if (path) {
return [NSURL fileURLWithPath:path
isDirectory:false];
}

return nil;
}

} // namespace linguine::alfredo
Binary file added assets/audio/Select 1.wav
Binary file not shown.
1 change: 1 addition & 0 deletions audio/audioengine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ enable_language(OBJCXX)

add_library(audioengine
src/AudioEngineAudioManager.mm
src/AudioEngineFileLoader.mm
)

set(CMAKE_OBJC_FLAGS "-fobjc-arc")
Expand Down
11 changes: 6 additions & 5 deletions audio/audioengine/include/AudioEngineAudioManager.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <AudioManager.h>
#include "audio/AudioManager.h"

#include <mutex>
#include <queue>
Expand All @@ -9,22 +9,23 @@
#import <AVFoundation/AVAudioFile.h>
#import <AVFoundation/AVAudioPlayerNode.h>

#include "AudioEngineFileLoader.h"

namespace linguine::audio {

class AudioEngineAudioManager : public AudioManager {
public:
AudioEngineAudioManager();
explicit AudioEngineAudioManager(std::unique_ptr<AudioEngineFileLoader> fileLoader);

~AudioEngineAudioManager() override;

void play() override;
void play(EffectType effectType) override;

private:
static constexpr uint8_t _maxChannels = 32;

std::unique_ptr<AudioEngineFileLoader> _fileLoader;
AVAudioEngine* _audioEngine;
AVAudioFile* _fileToPlay;

NSMutableArray<AVAudioPlayerNode*>* _playerNodes;

std::queue<AVAudioPlayerNode*> _nodePool;
Expand Down
23 changes: 23 additions & 0 deletions audio/audioengine/include/AudioEngineFileLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <unordered_map>

#import <AVFoundation/AVAudioFile.h>

#include <audio/EffectType.h>

namespace linguine::audio {

class AudioEngineFileLoader {
public:
virtual ~AudioEngineFileLoader() = default;

AVAudioFile* getAudioFileForEffect(EffectType effectType);

virtual NSURL* getUrlForEffect(EffectType effectType) = 0;

private:
std::unordered_map<EffectType, AVAudioFile*> _loadedFiles;
};

} // namespace linguine::audio
22 changes: 7 additions & 15 deletions audio/audioengine/src/AudioEngineAudioManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace linguine::audio {

AudioEngineAudioManager::AudioEngineAudioManager()
: _audioEngine([[AVAudioEngine alloc] init]),
AudioEngineAudioManager::AudioEngineAudioManager(std::unique_ptr<AudioEngineFileLoader> fileLoader)
: _fileLoader(std::move(fileLoader)),
_audioEngine([[AVAudioEngine alloc] init]),
_playerNodes([[NSMutableArray alloc] init]) {
auto outputFormat = [_audioEngine.outputNode inputFormatForBus:0];
auto inputFormat = [[AVAudioFormat alloc] initWithCommonFormat:outputFormat.commonFormat
Expand All @@ -30,7 +31,6 @@
}

NSError* error;

if (![_audioEngine startAndReturnError:&error]) {
NSLog(@"%@", error.localizedDescription);
return;
Expand All @@ -39,16 +39,6 @@
for (AVAudioPlayerNode* playerNode in _playerNodes) {
[playerNode play];
}

auto url = [NSURL fileURLWithPath:@"Balloon Pop 1.wav"];
//auto url = [[NSBundle mainBundle] URLForResource:@"Balloon Pop 1" withExtension:@"wav"];
_fileToPlay = [[AVAudioFile alloc] initForReading:url
error:&error];

if (error) {
NSLog(@"%@", [error localizedDescription]);
return;
}
}

AudioEngineAudioManager::~AudioEngineAudioManager() {
Expand All @@ -59,11 +49,13 @@
[_audioEngine stop];
}

void AudioEngineAudioManager::play() {
void AudioEngineAudioManager::play(EffectType effectType) {
auto playerNode = getPlayerNode();

if (playerNode) {
[playerNode scheduleFile:_fileToPlay
auto file = _fileLoader->getAudioFileForEffect(effectType);

[playerNode scheduleFile:file
atTime:nil
completionCallbackType:AVAudioPlayerNodeCompletionDataPlayedBack
completionHandler:^(AVAudioPlayerNodeCompletionCallbackType callbackType) {
Expand Down
28 changes: 28 additions & 0 deletions audio/audioengine/src/AudioEngineFileLoader.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "AudioEngineFileLoader.h"

namespace linguine::audio {

AVAudioFile* AudioEngineFileLoader::getAudioFileForEffect(EffectType effectType) {
auto existing = _loadedFiles.find(effectType);

if (existing != _loadedFiles.end()) {
return existing->second;
}

auto url = getUrlForEffect(effectType);

NSError* error;
auto file = [[AVAudioFile alloc] initForReading:url
error:&error];

if (error) {
NSLog(@"%@", [error localizedDescription]);
return nil;
}

_loadedFiles.insert({effectType, file});

return file;
}

} // namespace linguine::audio
2 changes: 1 addition & 1 deletion linguine/include/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

#include "ServiceLocator.h"

#include "AudioManager.h"
#include "InputManager.h"
#include "LifecycleManager.h"
#include "Logger.h"
#include "Scene.h"
#include "TimeManager.h"
#include "audio/AudioManager.h"
#include "entity/EntityManagerFactory.h"
#include "renderer/Renderer.h"

Expand Down
6 changes: 3 additions & 3 deletions linguine/include/ServiceLocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

#include <stdexcept>

#include "entity/EntityManagerFactory.h"
#include "renderer/Renderer.h"
#include "AudioManager.h"
#include "InputManager.h"
#include "LifecycleManager.h"
#include "Logger.h"
#include "TimeManager.h"
#include "audio/AudioManager.h"
#include "entity/EntityManagerFactory.h"
#include "renderer/Renderer.h"

namespace linguine {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#pragma once

#include "EffectType.h"

namespace linguine {

class AudioManager {
public:
virtual ~AudioManager() = default;

virtual void play() = 0;
virtual void play(EffectType effectType) = 0;
};

} // namespace linguine
10 changes: 10 additions & 0 deletions linguine/include/audio/EffectType.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

namespace linguine {

enum EffectType {
Pop,
Select
};

} // namespace linguine
4 changes: 2 additions & 2 deletions linguine/src/scenes/TestScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class TestScene : public Scene {
registerSystem(std::make_unique<GestureRecognitionSystem>(getEntityManager(), serviceLocator.get<InputManager>(), serviceLocator.get<Renderer>(), serviceLocator.get<TimeManager>()));
registerSystem(std::make_unique<SelectionDestructionSystem>(getEntityManager(), serviceLocator.get<AudioManager>()));
registerSystem(std::make_unique<FallerSystem>(getEntityManager()));
registerSystem(std::make_unique<RiserSystem>(getEntityManager()));
registerSystem(std::make_unique<RotatorSystem>(getEntityManager()));
registerSystem(std::make_unique<RiserSystem>(getEntityManager(), serviceLocator.get<AudioManager>()));
registerSystem(std::make_unique<RotatorSystem>(getEntityManager(), serviceLocator.get<AudioManager>()));
registerSystem(std::make_unique<TransformationSystem>(getEntityManager()));
registerSystem(std::make_unique<CameraSystem>(getEntityManager(), serviceLocator.get<Renderer>()));

Expand Down
4 changes: 3 additions & 1 deletion linguine/src/systems/RiserSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
namespace linguine {

void RiserSystem::update(float deltaTime) {
findEntities<Rising, Tapped>()->each([](Entity& entity) {
findEntities<Rising, Tapped>()->each([this](Entity& entity) {
const auto speed = entity.get<Rising>()->speed;
entity.remove<Rising>();

auto falling = entity.add<Falling>();
falling->speed = speed;

_audioManager.play(EffectType::Select);
});

findEntities<Rising, Transform>()->each([deltaTime](const Entity& entity) {
Expand Down
10 changes: 8 additions & 2 deletions linguine/src/systems/RiserSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

#include "System.h"

#include "audio/AudioManager.h"

namespace linguine {

class RiserSystem : public System {
public:
explicit RiserSystem(EntityManager& entityManager)
: System(entityManager) {}
explicit RiserSystem(EntityManager& entityManager,
AudioManager& audioManager)
: System(entityManager), _audioManager(audioManager) {}

void update(float deltaTime) override;

void fixedUpdate(float fixedDeltaTime) override {}

private:
AudioManager& _audioManager;
};

} // namespace linguine
3 changes: 2 additions & 1 deletion linguine/src/systems/RotatorSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
namespace linguine {

void RotatorSystem::update(float deltaTime) {
findEntities<Rotating, Tapped>()->each([](const Entity& entity) {
findEntities<Rotating, Tapped>()->each([this](const Entity& entity) {
const auto rotating = entity.get<Rotating>();
rotating->speed = -rotating->speed;
_audioManager.play(EffectType::Select);
});

findEntities<Rotating, Transform>()->each([deltaTime](const Entity& entity) {
Expand Down
10 changes: 8 additions & 2 deletions linguine/src/systems/RotatorSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

#include "System.h"

#include "audio/AudioManager.h"

namespace linguine {

class RotatorSystem : public System {
public:
explicit RotatorSystem(EntityManager& entityManager)
: System(entityManager) {}
explicit RotatorSystem(EntityManager& entityManager,
AudioManager& audioManager)
: System(entityManager), _audioManager(audioManager) {}

void update(float deltaTime) override;

void fixedUpdate(float fixedDeltaTime) override {}

private:
AudioManager& _audioManager;
};

} // namespace linguine
2 changes: 1 addition & 1 deletion linguine/src/systems/SelectionDestructionSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace linguine {

void SelectionDestructionSystem::update(float deltaTime) {
findEntities<LongPressed>()->each([this](Entity& entity) {
_audioManager.play();
_audioManager.play(EffectType::Pop);
entity.destroy();
});
}
Expand Down
2 changes: 1 addition & 1 deletion linguine/src/systems/SelectionDestructionSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "System.h"

#include "AudioManager.h"
#include "audio/AudioManager.h"

namespace linguine {

Expand Down
1 change: 1 addition & 0 deletions scampi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_executable(scampi
MACOSX_BUNDLE
src/main.mm
src/metalkit/ScampiViewDelegate.mm
src/platform/IosAudioEngineFileLoader.mm
src/platform/IosInputManager.cpp
src/platform/IosLifecycleManager.cpp
src/platform/IosTimeManager.cpp
Expand Down

0 comments on commit e7e58b0

Please sign in to comment.