123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /**************************************************************************/
- /* audio_stream_interactive.h */
- /**************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* https://godotengine.org */
- /**************************************************************************/
- /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
- /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /**************************************************************************/
- #ifndef AUDIO_STREAM_INTERACTIVE_H
- #define AUDIO_STREAM_INTERACTIVE_H
- #include "servers/audio/audio_stream.h"
- class AudioStreamPlaybackInteractive;
- class AudioStreamInteractive : public AudioStream {
- GDCLASS(AudioStreamInteractive, AudioStream)
- OBJ_SAVE_TYPE(AudioStream)
- public:
- enum TransitionFromTime {
- TRANSITION_FROM_TIME_IMMEDIATE,
- TRANSITION_FROM_TIME_NEXT_BEAT,
- TRANSITION_FROM_TIME_NEXT_BAR,
- TRANSITION_FROM_TIME_END,
- TRANSITION_FROM_TIME_MAX
- };
- enum TransitionToTime {
- TRANSITION_TO_TIME_SAME_POSITION,
- TRANSITION_TO_TIME_START,
- TRANSITION_TO_TIME_PREVIOUS_POSITION,
- TRANSITION_TO_TIME_MAX,
- };
- enum FadeMode {
- FADE_DISABLED,
- FADE_IN,
- FADE_OUT,
- FADE_CROSS,
- FADE_AUTOMATIC,
- FADE_MAX
- };
- enum AutoAdvanceMode {
- AUTO_ADVANCE_DISABLED,
- AUTO_ADVANCE_ENABLED,
- AUTO_ADVANCE_RETURN_TO_HOLD,
- };
- enum {
- CLIP_ANY = -1
- };
- private:
- friend class AudioStreamPlaybackInteractive;
- int sample_rate = 44100;
- bool stereo = true;
- int initial_clip = 0;
- double time = 0;
- enum {
- MAX_CLIPS = 63, // Because we use bitmasks for transition matching.
- MAX_TRANSITIONS = 63,
- };
- struct Clip {
- StringName name;
- Ref<AudioStream> stream;
- AutoAdvanceMode auto_advance = AUTO_ADVANCE_DISABLED;
- int auto_advance_next_clip = 0;
- };
- Clip clips[MAX_CLIPS];
- struct Transition {
- TransitionFromTime from_time = TRANSITION_FROM_TIME_NEXT_BEAT;
- TransitionToTime to_time = TRANSITION_TO_TIME_START;
- FadeMode fade_mode = FADE_AUTOMATIC;
- int fade_beats = 1;
- bool use_filler_clip = false;
- int filler_clip = 0;
- bool hold_previous = false;
- };
- struct TransitionKey {
- uint32_t from_clip;
- uint32_t to_clip;
- bool operator==(const TransitionKey &p_key) const {
- return from_clip == p_key.from_clip && to_clip == p_key.to_clip;
- }
- TransitionKey(uint32_t p_from_clip = 0, uint32_t p_to_clip = 0) {
- from_clip = p_from_clip;
- to_clip = p_to_clip;
- }
- };
- struct TransitionKeyHasher {
- static _FORCE_INLINE_ uint32_t hash(const TransitionKey &p_key) {
- uint32_t h = hash_murmur3_one_32(p_key.from_clip);
- return hash_murmur3_one_32(p_key.to_clip, h);
- }
- };
- HashMap<TransitionKey, Transition, TransitionKeyHasher> transition_map;
- uint64_t version = 1; // Used to stop playback instances for incompatibility.
- int clip_count = 0;
- HashSet<AudioStreamPlaybackInteractive *> playbacks;
- #ifdef TOOLS_ENABLED
- mutable String stream_name_cache;
- String _get_streams_hint() const;
- PackedStringArray _get_linked_undo_properties(const String &p_property, const Variant &p_new_value) const;
- void _inspector_array_swap_clip(uint32_t p_item_a, uint32_t p_item_b);
- #endif
- void _set_transitions(const Dictionary &p_transitions);
- Dictionary _get_transitions() const;
- public:
- // CLIPS
- void set_clip_count(int p_count);
- int get_clip_count() const;
- void set_initial_clip(int p_clip);
- int get_initial_clip() const;
- void set_clip_name(int p_clip, const StringName &p_name);
- StringName get_clip_name(int p_clip) const;
- void set_clip_stream(int p_clip, const Ref<AudioStream> &p_stream);
- Ref<AudioStream> get_clip_stream(int p_clip) const;
- void set_clip_auto_advance(int p_clip, AutoAdvanceMode p_mode);
- AutoAdvanceMode get_clip_auto_advance(int p_clip) const;
- void set_clip_auto_advance_next_clip(int p_clip, int p_index);
- int get_clip_auto_advance_next_clip(int p_clip) const;
- // TRANSITIONS
- void 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);
- TransitionFromTime get_transition_from_time(int p_from_clip, int p_to_clip) const;
- TransitionToTime get_transition_to_time(int p_from_clip, int p_to_clip) const;
- FadeMode get_transition_fade_mode(int p_from_clip, int p_to_clip) const;
- float get_transition_fade_beats(int p_from_clip, int p_to_clip) const;
- bool is_transition_using_filler_clip(int p_from_clip, int p_to_clip) const;
- int get_transition_filler_clip(int p_from_clip, int p_to_clip) const;
- bool is_transition_holding_previous(int p_from_clip, int p_to_clip) const;
- bool has_transition(int p_from_clip, int p_to_clip) const;
- void erase_transition(int p_from_clip, int p_to_clip);
- PackedInt32Array get_transition_list() const;
- virtual Ref<AudioStreamPlayback> instantiate_playback() override;
- virtual String get_stream_name() const override;
- virtual double get_length() const override { return 0; }
- AudioStreamInteractive();
- protected:
- virtual void get_parameter_list(List<Parameter> *r_parameters) override;
- static void _bind_methods();
- void _validate_property(PropertyInfo &r_property) const;
- };
- VARIANT_ENUM_CAST(AudioStreamInteractive::TransitionFromTime)
- VARIANT_ENUM_CAST(AudioStreamInteractive::TransitionToTime)
- VARIANT_ENUM_CAST(AudioStreamInteractive::AutoAdvanceMode)
- VARIANT_ENUM_CAST(AudioStreamInteractive::FadeMode)
- class AudioStreamPlaybackInteractive : public AudioStreamPlayback {
- GDCLASS(AudioStreamPlaybackInteractive, AudioStreamPlayback)
- friend class AudioStreamInteractive;
- private:
- Ref<AudioStreamInteractive> stream;
- uint64_t version = 0;
- enum {
- BUFFER_SIZE = 1024
- };
- AudioFrame mix_buffer[BUFFER_SIZE];
- AudioFrame temp_buffer[BUFFER_SIZE];
- struct State {
- Ref<AudioStream> stream;
- Ref<AudioStreamPlayback> playback;
- bool active = false;
- double fade_wait = 0; // Time to wait until fade kicks-in
- double fade_volume = 1.0;
- double fade_speed = 0; // Fade speed, negative or positive
- int auto_advance = -1;
- bool first_mix = true;
- double previous_position = 0;
- void reset_fade() {
- fade_wait = 0;
- fade_volume = 1.0;
- fade_speed = 0;
- }
- };
- State states[AudioStreamInteractive::MAX_CLIPS];
- int playback_current = -1;
- bool active = false;
- int return_memory = -1;
- void _mix_internal(int p_frames);
- void _mix_internal_state(int p_state_idx, int p_frames);
- void _queue(int p_to_clip_index, bool p_is_auto_advance);
- int switch_request = -1;
- protected:
- static void _bind_methods();
- public:
- virtual void start(double p_from_pos = 0.0) override;
- virtual void stop() override;
- virtual bool is_playing() const override;
- virtual int get_loop_count() const override; // times it looped
- virtual double get_playback_position() const override;
- virtual void seek(double p_time) override;
- virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
- virtual void tag_used_streams() override;
- void switch_to_clip_by_name(const StringName &p_name);
- void switch_to_clip(int p_index);
- virtual void set_parameter(const StringName &p_name, const Variant &p_value) override;
- virtual Variant get_parameter(const StringName &p_name) const override;
- AudioStreamPlaybackInteractive();
- ~AudioStreamPlaybackInteractive();
- };
- #endif // AUDIO_STREAM_INTERACTIVE_H
|