1 /*************************************************************************/
2 /* sample_editor_plugin.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 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 #include "sample_editor_plugin.h"
31
32 #include "editor/editor_settings.h"
33 #include "globals.h"
34 #include "io/resource_loader.h"
35
_input_event(InputEvent p_event)36 void SampleEditor::_input_event(InputEvent p_event) {
37 }
38
_notification(int p_what)39 void SampleEditor::_notification(int p_what) {
40
41 if (p_what == NOTIFICATION_FIXED_PROCESS) {
42 }
43
44 if (p_what == NOTIFICATION_ENTER_TREE) {
45 play->set_icon(get_icon("Play", "EditorIcons"));
46 stop->set_icon(get_icon("Stop", "EditorIcons"));
47 }
48
49 if (p_what == NOTIFICATION_READY) {
50
51 //get_scene()->connect("node_removed",this,"_node_removed");
52 }
53
54 if (p_what == NOTIFICATION_DRAW) {
55 }
56 }
57
_play_pressed()58 void SampleEditor::_play_pressed() {
59
60 player->play("default", true);
61 stop->set_pressed(false);
62 play->set_pressed(true);
63 }
_stop_pressed()64 void SampleEditor::_stop_pressed() {
65
66 player->stop_all();
67 play->set_pressed(false);
68 }
69
generate_preview_texture(const Ref<Sample> & p_sample,Ref<ImageTexture> & p_texture)70 void SampleEditor::generate_preview_texture(const Ref<Sample> &p_sample, Ref<ImageTexture> &p_texture) {
71
72 if (p_sample == NULL)
73 return;
74
75 DVector<uint8_t> data = p_sample->get_data();
76
77 DVector<uint8_t> img;
78 int w = p_texture->get_width();
79 int h = p_texture->get_height();
80 img.resize(w * h * 3);
81 DVector<uint8_t>::Write imgdata = img.write();
82 uint8_t *imgw = imgdata.ptr();
83 DVector<uint8_t>::Read sampledata = data.read();
84 const uint8_t *sdata = sampledata.ptr();
85
86 bool stereo = p_sample->is_stereo();
87 bool _16 = p_sample->get_format() == Sample::FORMAT_PCM16;
88 int len = p_sample->get_length();
89
90 if (len < 1)
91 return;
92
93 if (p_sample->get_format() == Sample::FORMAT_IMA_ADPCM) {
94
95 struct IMA_ADPCM_State {
96
97 int16_t step_index;
98 int32_t predictor;
99 /* values at loop point */
100 int16_t loop_step_index;
101 int32_t loop_predictor;
102 int32_t last_nibble;
103 int32_t loop_pos;
104 int32_t window_ofs;
105 const uint8_t *ptr;
106 } ima_adpcm;
107
108 ima_adpcm.step_index = 0;
109 ima_adpcm.predictor = 0;
110 ima_adpcm.loop_step_index = 0;
111 ima_adpcm.loop_predictor = 0;
112 ima_adpcm.last_nibble = -1;
113 ima_adpcm.loop_pos = 0x7FFFFFFF;
114 ima_adpcm.window_ofs = 0;
115 ima_adpcm.ptr = NULL;
116
117 for (int i = 0; i < w; i++) {
118
119 float max[2] = { -1e10, -1e10 };
120 float min[2] = { 1e10, 1e10 };
121 int from = i * len / w;
122 int to = (i + 1) * len / w;
123 if (to >= len)
124 to = len - 1;
125
126 for (int j = from; j < to; j++) {
127
128 while (j > ima_adpcm.last_nibble) {
129
130 static const int16_t _ima_adpcm_step_table[89] = {
131 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
132 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
133 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
134 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
135 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
136 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
137 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
138 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
139 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
140 };
141
142 static const int8_t _ima_adpcm_index_table[16] = {
143 -1, -1, -1, -1, 2, 4, 6, 8,
144 -1, -1, -1, -1, 2, 4, 6, 8
145 };
146
147 int16_t nibble, diff, step;
148
149 ima_adpcm.last_nibble++;
150 const uint8_t *src_ptr = sdata;
151
152 int ofs = ima_adpcm.last_nibble >> 1;
153
154 if (stereo)
155 ofs *= 2;
156
157 nibble = (ima_adpcm.last_nibble & 1) ?
158 (src_ptr[ofs] >> 4) :
159 (src_ptr[ofs] & 0xF);
160
161 step = _ima_adpcm_step_table[ima_adpcm.step_index];
162
163 ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
164 if (ima_adpcm.step_index < 0)
165 ima_adpcm.step_index = 0;
166 if (ima_adpcm.step_index > 88)
167 ima_adpcm.step_index = 88;
168
169 diff = step >> 3;
170 if (nibble & 1)
171 diff += step >> 2;
172 if (nibble & 2)
173 diff += step >> 1;
174 if (nibble & 4)
175 diff += step;
176 if (nibble & 8)
177 diff = -diff;
178
179 ima_adpcm.predictor += diff;
180 if (ima_adpcm.predictor < -0x8000)
181 ima_adpcm.predictor = -0x8000;
182 else if (ima_adpcm.predictor > 0x7FFF)
183 ima_adpcm.predictor = 0x7FFF;
184
185 /* store loop if there */
186 if (ima_adpcm.last_nibble == ima_adpcm.loop_pos) {
187
188 ima_adpcm.loop_step_index = ima_adpcm.step_index;
189 ima_adpcm.loop_predictor = ima_adpcm.predictor;
190 }
191 }
192
193 float v = ima_adpcm.predictor / 32767.0;
194 if (v > max[0])
195 max[0] = v;
196 if (v < min[0])
197 min[0] = v;
198 }
199
200 for (int j = 0; j < h; j++) {
201 float v = (j / (float)h) * 2.0 - 1.0;
202 uint8_t *imgofs = &imgw[(uint64_t(j) * w + i) * 3];
203 if (v > min[0] && v < max[0]) {
204 imgofs[0] = 255;
205 imgofs[1] = 150;
206 imgofs[2] = 80;
207 } else {
208 imgofs[0] = 0;
209 imgofs[1] = 0;
210 imgofs[2] = 0;
211 }
212 }
213 }
214 } else {
215 for (int i = 0; i < w; i++) {
216 // i trust gcc will optimize this loop
217 float max[2] = { -1e10, -1e10 };
218 float min[2] = { 1e10, 1e10 };
219 int c = stereo ? 2 : 1;
220 int from = uint64_t(i) * len / w;
221 int to = (uint64_t(i) + 1) * len / w;
222 if (to >= len)
223 to = len - 1;
224
225 if (_16) {
226 const int16_t *src = (const int16_t *)sdata;
227
228 for (int j = 0; j < c; j++) {
229
230 for (int k = from; k <= to; k++) {
231
232 float v = src[uint64_t(k) * c + j] / 32768.0;
233 if (v > max[j])
234 max[j] = v;
235 if (v < min[j])
236 min[j] = v;
237 }
238 }
239 } else {
240
241 const int8_t *src = (const int8_t *)sdata;
242
243 for (int j = 0; j < c; j++) {
244
245 for (int k = from; k <= to; k++) {
246
247 float v = src[uint64_t(k) * c + j] / 128.0;
248 if (v > max[j])
249 max[j] = v;
250 if (v < min[j])
251 min[j] = v;
252 }
253 }
254 }
255
256 if (!stereo) {
257 for (int j = 0; j < h; j++) {
258 float v = (j / (float)h) * 2.0 - 1.0;
259 uint8_t *imgofs = &imgw[(uint64_t(j) * w + i) * 3];
260 if (v > min[0] && v < max[0]) {
261 imgofs[0] = 255;
262 imgofs[1] = 150;
263 imgofs[2] = 80;
264 } else {
265 imgofs[0] = 0;
266 imgofs[1] = 0;
267 imgofs[2] = 0;
268 }
269 }
270 } else {
271
272 for (int j = 0; j < h; j++) {
273
274 int half;
275 float v;
276 if (j < (h / 2)) {
277 half = 0;
278 v = (j / (float)(h / 2)) * 2.0 - 1.0;
279 } else {
280 half = 1;
281 v = ((j - (h / 2)) / (float)(h / 2)) * 2.0 - 1.0;
282 }
283
284 uint8_t *imgofs = &imgw[(uint64_t(j) * w + i) * 3];
285 if (v > min[half] && v < max[half]) {
286 imgofs[0] = 255;
287 imgofs[1] = 150;
288 imgofs[2] = 80;
289 } else {
290 imgofs[0] = 0;
291 imgofs[1] = 0;
292 imgofs[2] = 0;
293 }
294 }
295 }
296 }
297 }
298
299 imgdata = DVector<uint8_t>::Write();
300
301 p_texture->set_data(Image(w, h, 0, Image::FORMAT_RGB, img));
302 }
303
_update_sample()304 void SampleEditor::_update_sample() {
305
306 player->stop_all();
307
308 generate_preview_texture(sample, peakdisplay);
309 info_label->set_text(TTR("Length:") + " " + String::num(sample->get_length() / (float)sample->get_mix_rate(), 2) + "s");
310
311 if (library->has_sample("default"))
312 library->remove_sample("default");
313
314 library->add_sample("default", sample);
315 }
316
edit(Ref<Sample> p_sample)317 void SampleEditor::edit(Ref<Sample> p_sample) {
318
319 sample = p_sample;
320
321 if (!sample.is_null())
322 _update_sample();
323 else {
324
325 hide();
326 set_fixed_process(false);
327 }
328 }
329
_bind_methods()330 void SampleEditor::_bind_methods() {
331
332 ObjectTypeDB::bind_method(_MD("_input_event"), &SampleEditor::_input_event);
333 ObjectTypeDB::bind_method(_MD("_play_pressed"), &SampleEditor::_play_pressed);
334 ObjectTypeDB::bind_method(_MD("_stop_pressed"), &SampleEditor::_stop_pressed);
335 }
336
SampleEditor()337 SampleEditor::SampleEditor() {
338
339 player = memnew(SamplePlayer);
340 add_child(player);
341 add_style_override("panel", get_stylebox("panel", "Panel"));
342 library = Ref<SampleLibrary>(memnew(SampleLibrary));
343 player->set_sample_library(library);
344 sample_texframe = memnew(TextureFrame);
345 add_child(sample_texframe);
346 sample_texframe->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5);
347 sample_texframe->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 5);
348 sample_texframe->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 30);
349 sample_texframe->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 5);
350
351 info_label = memnew(Label);
352 sample_texframe->add_child(info_label);
353 info_label->set_area_as_parent_rect();
354 info_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, 15);
355 info_label->set_margin(MARGIN_BOTTOM, 4);
356 info_label->set_margin(MARGIN_RIGHT, 4);
357 info_label->set_align(Label::ALIGN_RIGHT);
358
359 play = memnew(Button);
360
361 play->set_pos(Point2(5, 5));
362 play->set_size(Size2(1, 1));
363 play->set_toggle_mode(true);
364 add_child(play);
365
366 stop = memnew(Button);
367
368 stop->set_pos(Point2(35, 5));
369 stop->set_size(Size2(1, 1));
370 stop->set_toggle_mode(true);
371 add_child(stop);
372
373 peakdisplay = Ref<ImageTexture>(memnew(ImageTexture));
374 peakdisplay->create(EDITOR_DEF("audio/sample_editor_preview_width", 512), EDITOR_DEF("audio/sample_editor_preview_height", 128), Image::FORMAT_RGB);
375 sample_texframe->set_expand(true);
376 sample_texframe->set_texture(peakdisplay);
377
378 play->connect("pressed", this, "_play_pressed");
379 stop->connect("pressed", this, "_stop_pressed");
380
381 set_custom_minimum_size(Size2(1, 150) * EDSCALE);
382 }
383
edit(Object * p_object)384 void SampleEditorPlugin::edit(Object *p_object) {
385
386 Sample *s = p_object->cast_to<Sample>();
387 if (!s)
388 return;
389
390 sample_editor->edit(Ref<Sample>(s));
391 }
392
handles(Object * p_object) const393 bool SampleEditorPlugin::handles(Object *p_object) const {
394
395 return p_object->is_type("Sample");
396 }
397
make_visible(bool p_visible)398 void SampleEditorPlugin::make_visible(bool p_visible) {
399
400 if (p_visible) {
401 sample_editor->show();
402 // sample_editor->set_process(true);
403 } else {
404
405 sample_editor->hide();
406 // sample_editor->set_process(false);
407 }
408 }
409
SampleEditorPlugin(EditorNode * p_node)410 SampleEditorPlugin::SampleEditorPlugin(EditorNode *p_node) {
411
412 editor = p_node;
413 sample_editor = memnew(SampleEditor);
414 add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM, sample_editor);
415 sample_editor->hide();
416 }
417
~SampleEditorPlugin()418 SampleEditorPlugin::~SampleEditorPlugin() {
419 }
420