Path: blob/master/modules/interactive_music/audio_stream_interactive.h
10277 views
/**************************************************************************/1/* audio_stream_interactive.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "servers/audio/audio_stream.h"3334class AudioStreamPlaybackInteractive;3536class AudioStreamInteractive : public AudioStream {37GDCLASS(AudioStreamInteractive, AudioStream)38OBJ_SAVE_TYPE(AudioStream)39public:40enum TransitionFromTime {41TRANSITION_FROM_TIME_IMMEDIATE,42TRANSITION_FROM_TIME_NEXT_BEAT,43TRANSITION_FROM_TIME_NEXT_BAR,44TRANSITION_FROM_TIME_END,45TRANSITION_FROM_TIME_MAX46};4748enum TransitionToTime {49TRANSITION_TO_TIME_SAME_POSITION,50TRANSITION_TO_TIME_START,51TRANSITION_TO_TIME_PREVIOUS_POSITION,52TRANSITION_TO_TIME_MAX,53};5455enum FadeMode {56FADE_DISABLED,57FADE_IN,58FADE_OUT,59FADE_CROSS,60FADE_AUTOMATIC,61FADE_MAX62};6364enum AutoAdvanceMode {65AUTO_ADVANCE_DISABLED,66AUTO_ADVANCE_ENABLED,67AUTO_ADVANCE_RETURN_TO_HOLD,68};6970enum {71CLIP_ANY = -172};7374private:75friend class AudioStreamPlaybackInteractive;76int sample_rate = 44100;77bool stereo = true;78int initial_clip = 0;7980double time = 0;8182enum {83MAX_CLIPS = 63, // Because we use bitmasks for transition matching.84MAX_TRANSITIONS = 63,85};8687struct Clip {88StringName name;89Ref<AudioStream> stream;9091AutoAdvanceMode auto_advance = AUTO_ADVANCE_DISABLED;92int auto_advance_next_clip = 0;93};9495Clip clips[MAX_CLIPS];9697struct Transition {98TransitionFromTime from_time = TRANSITION_FROM_TIME_NEXT_BEAT;99TransitionToTime to_time = TRANSITION_TO_TIME_START;100FadeMode fade_mode = FADE_AUTOMATIC;101float fade_beats = 1;102bool use_filler_clip = false;103int filler_clip = 0;104bool hold_previous = false;105};106107struct TransitionKey {108uint32_t from_clip;109uint32_t to_clip;110bool operator==(const TransitionKey &p_key) const {111return from_clip == p_key.from_clip && to_clip == p_key.to_clip;112}113TransitionKey(uint32_t p_from_clip = 0, uint32_t p_to_clip = 0) {114from_clip = p_from_clip;115to_clip = p_to_clip;116}117};118119struct TransitionKeyHasher {120static _FORCE_INLINE_ uint32_t hash(const TransitionKey &p_key) {121uint32_t h = hash_murmur3_one_32(p_key.from_clip);122return hash_murmur3_one_32(p_key.to_clip, h);123}124};125126HashMap<TransitionKey, Transition, TransitionKeyHasher> transition_map;127128uint64_t version = 1; // Used to stop playback instances for incompatibility.129int clip_count = 0;130131HashSet<AudioStreamPlaybackInteractive *> playbacks;132133#ifdef TOOLS_ENABLED134135mutable String stream_name_cache;136String _get_streams_hint() const;137PackedStringArray _get_linked_undo_properties(const String &p_property, const Variant &p_new_value) const;138void _inspector_array_swap_clip(uint32_t p_item_a, uint32_t p_item_b);139140#endif141142void _set_transitions(const Dictionary &p_transitions);143Dictionary _get_transitions() const;144145public:146// CLIPS147void set_clip_count(int p_count);148int get_clip_count() const;149150void set_initial_clip(int p_clip);151int get_initial_clip() const;152153void set_clip_name(int p_clip, const StringName &p_name);154StringName get_clip_name(int p_clip) const;155156void set_clip_stream(int p_clip, const Ref<AudioStream> &p_stream);157Ref<AudioStream> get_clip_stream(int p_clip) const;158159void set_clip_auto_advance(int p_clip, AutoAdvanceMode p_mode);160AutoAdvanceMode get_clip_auto_advance(int p_clip) const;161162void set_clip_auto_advance_next_clip(int p_clip, int p_index);163int get_clip_auto_advance_next_clip(int p_clip) const;164165// TRANSITIONS166167void add_transition(int p_from_clip, int p_to_clip, TransitionFromTime p_from_time, TransitionToTime p_to_time, FadeMode p_fade_mode, float p_fade_beats, bool p_use_filler_flip = false, int p_filler_clip = -1, bool p_hold_previous = false);168TransitionFromTime get_transition_from_time(int p_from_clip, int p_to_clip) const;169TransitionToTime get_transition_to_time(int p_from_clip, int p_to_clip) const;170FadeMode get_transition_fade_mode(int p_from_clip, int p_to_clip) const;171float get_transition_fade_beats(int p_from_clip, int p_to_clip) const;172bool is_transition_using_filler_clip(int p_from_clip, int p_to_clip) const;173int get_transition_filler_clip(int p_from_clip, int p_to_clip) const;174bool is_transition_holding_previous(int p_from_clip, int p_to_clip) const;175176bool has_transition(int p_from_clip, int p_to_clip) const;177void erase_transition(int p_from_clip, int p_to_clip);178179PackedInt32Array get_transition_list() const;180181virtual Ref<AudioStreamPlayback> instantiate_playback() override;182virtual String get_stream_name() const override;183virtual double get_length() const override { return 0; }184virtual bool is_meta_stream() const override { return true; }185186AudioStreamInteractive();187188protected:189virtual void get_parameter_list(List<Parameter> *r_parameters) override;190191static void _bind_methods();192void _validate_property(PropertyInfo &r_property) const;193};194195VARIANT_ENUM_CAST(AudioStreamInteractive::TransitionFromTime)196VARIANT_ENUM_CAST(AudioStreamInteractive::TransitionToTime)197VARIANT_ENUM_CAST(AudioStreamInteractive::AutoAdvanceMode)198VARIANT_ENUM_CAST(AudioStreamInteractive::FadeMode)199200class AudioStreamPlaybackInteractive : public AudioStreamPlayback {201GDCLASS(AudioStreamPlaybackInteractive, AudioStreamPlayback)202friend class AudioStreamInteractive;203204private:205Ref<AudioStreamInteractive> stream;206uint64_t version = 0;207208enum {209BUFFER_SIZE = 1024210};211212AudioFrame mix_buffer[BUFFER_SIZE];213AudioFrame temp_buffer[BUFFER_SIZE];214215struct State {216Ref<AudioStream> stream;217Ref<AudioStreamPlayback> playback;218bool active = false;219double fade_wait = 0; // Time to wait until fade kicks-in220double fade_volume = 1.0;221double fade_speed = 0; // Fade speed, negative or positive222int auto_advance = -1;223bool first_mix = true;224double previous_position = 0;225226void reset_fade() {227fade_wait = 0;228fade_volume = 1.0;229fade_speed = 0;230}231};232233State states[AudioStreamInteractive::MAX_CLIPS];234int playback_current = -1;235236bool active = false;237int return_memory = -1;238239void _mix_internal(int p_frames);240void _mix_internal_state(int p_state_idx, int p_frames);241242void _queue(int p_to_clip_index, bool p_is_auto_advance);243244int switch_request = -1;245246protected:247static void _bind_methods();248249public:250virtual void start(double p_from_pos = 0.0) override;251virtual void stop() override;252virtual bool is_playing() const override;253virtual int get_loop_count() const override; // times it looped254virtual double get_playback_position() const override;255virtual void seek(double p_time) override;256virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;257258virtual void tag_used_streams() override;259260void switch_to_clip_by_name(const StringName &p_name);261void switch_to_clip(int p_index);262int get_current_clip_index() const;263264virtual void set_parameter(const StringName &p_name, const Variant &p_value) override;265virtual Variant get_parameter(const StringName &p_name) const override;266267AudioStreamPlaybackInteractive();268~AudioStreamPlaybackInteractive();269};270271272