diff options
Diffstat (limited to 'servers/audio')
-rw-r--r-- | servers/audio/audio_stream.cpp | 114 | ||||
-rw-r--r-- | servers/audio/audio_stream.h | 57 |
2 files changed, 171 insertions, 0 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 113f23f8f2..eef8aba0c4 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "audio_stream.h" +#include "os/os.h" ////////////////////////////// @@ -99,6 +100,119 @@ void AudioStream::_bind_methods() { //////////////////////////////// +Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() { + Ref<AudioStreamPlaybackMicrophone> playback; + playback.instance(); + + playbacks.insert(playback.ptr()); + + playback->microphone = Ref<AudioStreamMicrophone>((AudioStreamMicrophone *)this); + playback->active = false; + + return playback; +} + +String AudioStreamMicrophone::get_stream_name() const { + + //if (audio_stream.is_valid()) { + //return "Random: " + audio_stream->get_name(); + //} + return "Microphone"; +} + +float AudioStreamMicrophone::get_length() const { + return 0; +} + +void AudioStreamMicrophone::_bind_methods() { +} + +AudioStreamMicrophone::AudioStreamMicrophone() { +} + +void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) { + + AudioDriver::get_singleton()->lock(); + + Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer(); + unsigned int input_size = AudioDriver::get_singleton()->get_input_size(); + + // p_frames is multipled by two since an AudioFrame is stereo + if ((p_frames + MICROPHONE_PLAYBACK_DELAY * 2) > input_size) { + for (int i = 0; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0.0f, 0.0f); + } + input_ofs = 0; + } else { + for (int i = 0; i < p_frames; i++) { + if (input_size >= input_ofs) { + float l = (buf[input_ofs++] >> 16) / 32768.f; + if (input_ofs >= buf.size()) { + input_ofs = 0; + } + float r = (buf[input_ofs++] >> 16) / 32768.f; + if (input_ofs >= buf.size()) { + input_ofs = 0; + } + + p_buffer[i] = AudioFrame(l, r); + } else { + p_buffer[i] = AudioFrame(0.0f, 0.0f); + } + } + } + + AudioDriver::get_singleton()->unlock(); +} + +void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { + AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames); +} + +float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() { + return AudioDriver::get_singleton()->get_mix_rate(); +} + +void AudioStreamPlaybackMicrophone::start(float p_from_pos) { + input_ofs = 0; + + AudioDriver::get_singleton()->capture_start(); + + active = true; + _begin_resample(); +} + +void AudioStreamPlaybackMicrophone::stop() { + AudioDriver::get_singleton()->capture_stop(); + active = false; +} + +bool AudioStreamPlaybackMicrophone::is_playing() const { + return active; +} + +int AudioStreamPlaybackMicrophone::get_loop_count() const { + return 0; +} + +float AudioStreamPlaybackMicrophone::get_playback_position() const { + return 0; +} + +void AudioStreamPlaybackMicrophone::seek(float p_time) { + return; // Can't seek a microphone input +} + +AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() { + microphone->playbacks.erase(this); + stop(); +} + +AudioStreamPlaybackMicrophone::AudioStreamPlaybackMicrophone() { +} + +//////////////////////////////// + void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) { audio_stream = p_audio_stream; diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 3312ce1ff6..66e1b6ee2f 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -94,6 +94,63 @@ public: virtual float get_length() const = 0; //if supported, otherwise return 0 }; +// Microphone + +class AudioStreamPlaybackMicrophone; + +class AudioStreamMicrophone : public AudioStream { + + GDCLASS(AudioStreamMicrophone, AudioStream) + friend class AudioStreamPlaybackMicrophone; + + Set<AudioStreamPlaybackMicrophone *> playbacks; + +protected: + static void _bind_methods(); + +public: + virtual Ref<AudioStreamPlayback> instance_playback(); + virtual String get_stream_name() const; + + virtual float get_length() const; //if supported, otherwise return 0 + + AudioStreamMicrophone(); +}; + +class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled { + + GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback) + friend class AudioStreamMicrophone; + + const int MICROPHONE_PLAYBACK_DELAY = 256; + + bool active; + unsigned int input_ofs; + + Ref<AudioStreamMicrophone> microphone; + +protected: + virtual void _mix_internal(AudioFrame *p_buffer, int p_frames); + virtual float get_stream_sampling_rate(); + +public: + virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); + + virtual void start(float p_from_pos = 0.0); + virtual void stop(); + virtual bool is_playing() const; + + virtual int get_loop_count() const; //times it looped + + virtual float get_playback_position() const; + virtual void seek(float p_time); + + ~AudioStreamPlaybackMicrophone(); + AudioStreamPlaybackMicrophone(); +}; + +// + class AudioStreamPlaybackRandomPitch; class AudioStreamRandomPitch : public AudioStream { |