Experimental microphone support.
This commit is contained in:
@ -125,6 +125,28 @@ void AudioDriverDummy::finish() {
|
||||
thread = NULL;
|
||||
};
|
||||
|
||||
bool AudioDriverDummy::capture_device_start(StringName p_name) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioDriverDummy::capture_device_stop(StringName p_name) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PoolStringArray AudioDriverDummy::capture_device_get_names() {
|
||||
|
||||
PoolStringArray names;
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
StringName AudioDriverDummy::capture_device_get_default_name() {
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
AudioDriverDummy::AudioDriverDummy() {
|
||||
|
||||
mutex = NULL;
|
||||
|
||||
@ -68,6 +68,11 @@ public:
|
||||
virtual void unlock();
|
||||
virtual void finish();
|
||||
|
||||
virtual bool capture_device_start(StringName p_name);
|
||||
virtual bool capture_device_stop(StringName p_name);
|
||||
virtual PoolStringArray capture_device_get_names();
|
||||
virtual StringName capture_device_get_default_name();
|
||||
|
||||
AudioDriverDummy();
|
||||
~AudioDriverDummy();
|
||||
};
|
||||
|
||||
@ -99,6 +99,129 @@ 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";
|
||||
}
|
||||
|
||||
void AudioStreamMicrophone::set_microphone_name(const String &p_name) {
|
||||
if (microphone_name != p_name) {
|
||||
microphone_name = p_name;
|
||||
|
||||
for (Set<AudioStreamPlaybackMicrophone *>::Element *E = playbacks.front(); E; E = E->next()) {
|
||||
if (E->get()->active) {
|
||||
// Is this the right thing to do?
|
||||
E->get()->stop();
|
||||
E->get()->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringName AudioStreamMicrophone::get_microphone_name() const {
|
||||
return microphone_name;
|
||||
}
|
||||
|
||||
float AudioStreamMicrophone::get_length() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioStreamMicrophone::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_microphone_name", "name"), &AudioStreamMicrophone::set_microphone_name);
|
||||
ClassDB::bind_method(D_METHOD("get_microphone_name"), &AudioStreamMicrophone::get_microphone_name);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "microphone_name"), "set_microphone_name", "get_microphone_name");
|
||||
}
|
||||
|
||||
AudioStreamMicrophone::AudioStreamMicrophone() {
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
|
||||
AudioDriver::MicrophoneDeviceOutput *microphone_device_output = reciever->owner;
|
||||
const Vector<AudioFrame> &source_buffer = microphone_device_output->get_buffer();
|
||||
|
||||
if (microphone_device_output->get_read_index() >= 0) {
|
||||
for (int i = 0; i < p_frames; i++) {
|
||||
p_buffer[i] = source_buffer[internal_mic_offset + microphone_device_output->get_read_index() + i];
|
||||
}
|
||||
}
|
||||
|
||||
internal_mic_offset += p_frames;
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames);
|
||||
internal_mic_offset = 0; // Reset
|
||||
}
|
||||
|
||||
float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
|
||||
return reciever->owner->get_mix_rate();
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
|
||||
active = true;
|
||||
|
||||
// note: can this be called twice?
|
||||
reciever = AudioServer::get_singleton()->create_microphone_reciever(microphone->get_microphone_name());
|
||||
if (reciever == NULL) {
|
||||
active = false;
|
||||
}
|
||||
|
||||
_begin_resample();
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackMicrophone::stop() {
|
||||
active = false;
|
||||
if (reciever != NULL) {
|
||||
AudioServer::get_singleton()->destroy_microphone_reciever(reciever);
|
||||
reciever = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
internal_mic_offset = 0;
|
||||
reciever = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) {
|
||||
|
||||
audio_stream = p_audio_stream;
|
||||
|
||||
@ -94,6 +94,66 @@ 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;
|
||||
StringName microphone_name;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual Ref<AudioStreamPlayback> instance_playback();
|
||||
virtual String get_stream_name() const;
|
||||
|
||||
void set_microphone_name(const String &p_name);
|
||||
StringName get_microphone_name() const;
|
||||
|
||||
virtual float get_length() const; //if supported, otherwise return 0
|
||||
|
||||
AudioStreamMicrophone();
|
||||
};
|
||||
|
||||
class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
|
||||
|
||||
GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback)
|
||||
friend class AudioStreamMicrophone;
|
||||
|
||||
bool active;
|
||||
uint64_t internal_mic_offset;
|
||||
|
||||
Ref<AudioStreamMicrophone> microphone;
|
||||
AudioDriver::MicrophoneReciever *reciever;
|
||||
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user