1 /*************************************************************************/
2 /*  audio_stream_sample.h                                                */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #ifndef AUDIO_STREAM_SAMPLE_H
32 #define AUDIO_STREAM_SAMPLE_H
33 
34 #include "servers/audio/audio_stream.h"
35 
36 class AudioStreamSample;
37 
38 class AudioStreamPlaybackSample : public AudioStreamPlayback {
39 
40 	GDCLASS(AudioStreamPlaybackSample, AudioStreamPlayback);
41 	enum {
42 		MIX_FRAC_BITS = 13,
43 		MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
44 		MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
45 	};
46 
47 	struct IMA_ADPCM_State {
48 
49 		int16_t step_index;
50 		int32_t predictor;
51 		/* values at loop point */
52 		int16_t loop_step_index;
53 		int32_t loop_predictor;
54 		int32_t last_nibble;
55 		int32_t loop_pos;
56 		int32_t window_ofs;
57 	} ima_adpcm[2];
58 
59 	int64_t offset;
60 	int sign;
61 	bool active;
62 	friend class AudioStreamSample;
63 	Ref<AudioStreamSample> base;
64 
65 	template <class Depth, bool is_stereo, bool is_ima_adpcm>
66 	void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm);
67 
68 public:
69 	virtual void start(float p_from_pos = 0.0);
70 	virtual void stop();
71 	virtual bool is_playing() const;
72 
73 	virtual int get_loop_count() const; //times it looped
74 
75 	virtual float get_playback_position() const;
76 	virtual void seek(float p_time);
77 
78 	virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
79 
80 	AudioStreamPlaybackSample();
81 };
82 
83 class AudioStreamSample : public AudioStream {
84 	GDCLASS(AudioStreamSample, AudioStream);
85 	RES_BASE_EXTENSION("sample")
86 
87 public:
88 	enum Format {
89 		FORMAT_8_BITS,
90 		FORMAT_16_BITS,
91 		FORMAT_IMA_ADPCM
92 	};
93 
94 	enum LoopMode {
95 		LOOP_DISABLED,
96 		LOOP_FORWARD,
97 		LOOP_PING_PONG,
98 		LOOP_BACKWARD
99 	};
100 
101 private:
102 	friend class AudioStreamPlaybackSample;
103 
104 	enum {
105 		DATA_PAD = 16 //padding for interpolation
106 	};
107 
108 	Format format;
109 	LoopMode loop_mode;
110 	bool stereo;
111 	int loop_begin;
112 	int loop_end;
113 	int mix_rate;
114 	void *data;
115 	uint32_t data_bytes;
116 
117 protected:
118 	static void _bind_methods();
119 
120 public:
121 	void set_format(Format p_format);
122 	Format get_format() const;
123 
124 	void set_loop_mode(LoopMode p_loop_mode);
125 	LoopMode get_loop_mode() const;
126 
127 	void set_loop_begin(int p_frame);
128 	int get_loop_begin() const;
129 
130 	void set_loop_end(int p_frame);
131 	int get_loop_end() const;
132 
133 	void set_mix_rate(int p_hz);
134 	int get_mix_rate() const;
135 
136 	void set_stereo(bool p_enable);
137 	bool is_stereo() const;
138 
139 	virtual float get_length() const; //if supported, otherwise return 0
140 
141 	void set_data(const PoolVector<uint8_t> &p_data);
142 	PoolVector<uint8_t> get_data() const;
143 
144 	Error save_to_wav(const String &p_path);
145 
146 	virtual Ref<AudioStreamPlayback> instance_playback();
147 	virtual String get_stream_name() const;
148 
149 	AudioStreamSample();
150 	~AudioStreamSample();
151 };
152 
153 VARIANT_ENUM_CAST(AudioStreamSample::Format)
154 VARIANT_ENUM_CAST(AudioStreamSample::LoopMode)
155 
156 #endif // AUDIO_STREAM_SAMPLE_H
157