#pragma once #include #include #include #include #include #include "typedefs.hpp" #include "audio/audio.hpp" #ifdef __APPLE__ #include #include #else #include #include #endif namespace audio { struct ALBuffer; class ALAudio; class PCMStream; class ALSound : public Sound { ALAudio* al; uint buffer; std::shared_ptr pcm; duration_t duration; public: ALSound( ALAudio* al, uint buffer, const std::shared_ptr& pcm, bool keepPCM ); ~ALSound(); duration_t getDuration() const override { return duration; } std::shared_ptr getPCM() const override { return pcm; } std::unique_ptr newInstance(int priority, int channel) const override; }; class ALStream : public Stream { static inline constexpr size_t BUFFER_SIZE = 44100; ALAudio* al; std::shared_ptr source; std::queue unusedBuffers; speakerid_t speaker = 0; bool keepSource; char buffer[BUFFER_SIZE]; bool loop = false; bool stopOnEnd = false; bool preloadBuffer(uint buffer, bool loop); void unqueueBuffers(uint alsource); uint enqueueBuffers(uint alsource); public: size_t totalPlayedSamples = 0; ALStream( ALAudio* al, std::shared_ptr source, bool keepSource ); ~ALStream(); std::shared_ptr getSource() const override; void bindSpeaker(speakerid_t speakerid) override; std::unique_ptr createSpeaker(bool loop, int channel) override; speakerid_t getSpeaker() const override; void update(double delta) override; duration_t getTime() const override; void setTime(duration_t time) override; static inline constexpr uint STREAM_BUFFERS = 3; bool isStopOnEnd() const override; void setStopOnEnd(bool stopOnEnd) override; }; class ALInputDevice : public InputDevice { public: ALInputDevice( ALAudio* al, ALCdevice* device, uint channels, uint bitsPerSample, uint sampleRate ); ~ALInputDevice() override; void startCapture() override; void stopCapture() override; uint getChannels() const override; uint getSampleRate() const override; uint getBitsPerSample() const override; const std::string& getDeviceSpecifier() const override; size_t read(char* buffer, size_t bufferSize) override; private: ALCdevice* device; uint channels; uint bitsPerSample; uint sampleRate; std::string deviceSpecifier; }; /// @brief AL source adapter class ALSpeaker : public Speaker { ALAudio* al; int priority; int channel; float volume = 0.0f; public: ALStream* stream = nullptr; bool manuallyStopped = true; bool paused = false; uint source; duration_t duration = 0.0f; ALSpeaker(ALAudio* al, uint source, int priority, int channel); ~ALSpeaker(); void update(const Channel* channel) override; int getChannel() const override; State getState() const override; float getVolume() const override; void setVolume(float volume) override; float getPitch() const override; void setPitch(float pitch) override; bool isLoop() const override; void setLoop(bool loop) override; void play() override; void pause() override; void stop() override; duration_t getTime() const override; duration_t getDuration() const override; void setTime(duration_t time) override; void setPosition(glm::vec3 pos) override; glm::vec3 getPosition() const override; void setVelocity(glm::vec3 vel) override; glm::vec3 getVelocity() const override; void setRelative(bool relative) override; bool isRelative() const override; int getPriority() const override; bool isManuallyStopped() const override; }; class ALAudio : public Backend { ALCdevice* device; ALCcontext* context; std::vector allsources; std::vector freesources; std::vector allbuffers; std::vector freebuffers; uint maxSources = 256; public: ALAudio(ALCdevice* device, ALCcontext* context); ~ALAudio(); uint getFreeSource(); uint getFreeBuffer(); void freeSource(uint source); void freeBuffer(uint buffer); std::unique_ptr createSound( std::shared_ptr pcm, bool keepPCM ) override; std::unique_ptr openStream( std::shared_ptr stream, bool keepSource ) override; std::unique_ptr openInputDevice( const std::string& deviceName, uint sampleRate, uint channels, uint bitsPerSample ) override; std::vector getOutputDeviceNames() override; std::vector getInputDeviceNames() override; void setListener( glm::vec3 position, glm::vec3 velocity, glm::vec3 lookAt, glm::vec3 up ) override; void update(double delta) override; bool isDummy() const override { return false; } static std::unique_ptr create(); }; }