1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/ags_phase_shift_util.h>
21 
22 #include <ags/audio/ags_audio_signal.h>
23 #include <ags/audio/ags_audio_buffer_util.h>
24 
25 gpointer ags_phase_shift_util_strct_copy(gpointer ptr);
26 void ags_phase_shift_util_strct_free(gpointer ptr);
27 
28 /**
29  * SECTION:ags_phase_shift_util
30  * @short_description: phase shift util
31  * @title: AgsPhaseShiftUtil
32  * @section_id:
33  * @include: ags/audio/ags_phase_shift_util.h
34  *
35  * Utility functions to compute phase shift.
36  */
37 
38 
39 GType
ags_phase_shift_util_get_type(void)40 ags_phase_shift_util_get_type(void)
41 {
42   static volatile gsize g_define_type_id__volatile = 0;
43 
44   if(g_once_init_enter (&g_define_type_id__volatile)){
45     GType ags_type_phase_shift_util = 0;
46 
47     ags_type_phase_shift_util =
48       g_boxed_type_register_static("AgsPhaseShiftUtil",
49 				   (GBoxedCopyFunc) ags_phase_shift_util_strct_copy,
50 				   (GBoxedFreeFunc) ags_phase_shift_util_strct_free);
51 
52     g_once_init_leave(&g_define_type_id__volatile, ags_type_phase_shift_util);
53   }
54 
55   return g_define_type_id__volatile;
56 }
57 
58 gpointer
ags_phase_shift_util_strct_copy(gpointer ptr)59 ags_phase_shift_util_strct_copy(gpointer ptr)
60 {
61   gpointer retval;
62 
63   retval = g_memdup(ptr, sizeof(AgsPhaseShiftUtil));
64 
65   return(retval);
66 }
67 
68 void
ags_phase_shift_util_strct_free(gpointer ptr)69 ags_phase_shift_util_strct_free(gpointer ptr)
70 {
71   g_free(ptr);
72 }
73 
74 /**
75  * ags_phase_shift_util_compute_s8:
76  * @destination: the destination audio buffer
77  * @source: the source audio buffer
78  * @buffer_length: the audio buffer's length
79  * @samplerate: the samplerate
80  * @frequency: the frequency
81  * @amount: the amount
82  * @phase: the phase
83  *
84  * Compute phase shift of audio buffer at @frequency with @amount with
85  * max radian 2 * M_PI.
86  *
87  * Since: 3.8.0
88  */
89 void
ags_phase_shift_util_compute_s8(gint8 * destination,gint8 * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)90 ags_phase_shift_util_compute_s8(gint8 *destination,
91 				gint8 *source,
92 				guint buffer_length,
93 				guint samplerate,
94 				gdouble frequency,
95 				gdouble amount,
96 				gdouble phase)
97 {
98   gdouble freq_period, amount_period;
99   gdouble phase_period;
100   gdouble phase_shift;
101   guint i;
102 
103   if(destination == NULL ||
104      source == NULL ||
105      buffer_length == 0){
106     return;
107   }
108 
109   freq_period = samplerate / frequency;
110 
111   amount_period = (amount / (2.0 * M_PI)) * freq_period;
112 
113   phase_period = (phase / (2.0 * M_PI)) * freq_period;
114 
115   for(i = 0; i < buffer_length; i++){
116     phase_shift = ((amount / (2.0 * M_PI)) * (G_MAXINT8 / 2.0)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
117 
118     destination[i] = 0.5 * (phase_shift + source[i]);
119   }
120 }
121 
122 /**
123  * ags_phase_shift_util_compute_s16:
124  * @destination: the destination audio buffer
125  * @source: the source audio buffer
126  * @buffer_length: the audio buffer's length
127  * @samplerate: the samplerate
128  * @frequency: the frequency
129  * @amount: the amount
130  * @phase: the phase
131  *
132  * Compute phase shift of audio buffer at @frequency with @amount with
133  * max radian 2 * M_PI.
134  *
135  * Since: 3.8.0
136  */
137 void
ags_phase_shift_util_compute_s16(gint16 * destination,gint16 * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)138 ags_phase_shift_util_compute_s16(gint16 *destination,
139 				 gint16 *source,
140 				 guint buffer_length,
141 				 guint samplerate,
142 				 gdouble frequency,
143 				 gdouble amount,
144 				 gdouble phase)
145 {
146   gdouble freq_period, amount_period;
147   gdouble phase_period;
148   gdouble phase_shift;
149   guint i;
150 
151   if(destination == NULL ||
152      source == NULL ||
153      buffer_length == 0){
154     return;
155   }
156 
157   freq_period = samplerate / frequency;
158 
159   amount_period = (amount / (2.0 * M_PI)) * freq_period;
160 
161   phase_period = (phase / (2.0 * M_PI)) * freq_period;
162 
163   for(i = 0; i < buffer_length; i++){
164     phase_shift = ((amount / (2.0 * M_PI)) * (G_MAXINT16 / 2.0)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
165 
166     destination[i] = 0.5 * (phase_shift + source[i]);
167   }
168 }
169 
170 /**
171  * ags_phase_shift_util_compute_s24:
172  * @destination: the destination audio buffer
173  * @source: the source audio buffer
174  * @buffer_length: the audio buffer's length
175  * @samplerate: the samplerate
176  * @frequency: the frequency
177  * @amount: the amount
178  * @phase: the phase
179  *
180  * Compute phase shift of audio buffer at @frequency with @amount with
181  * max radian 2 * M_PI.
182  *
183  * Since: 3.8.0
184  */
185 void
ags_phase_shift_util_compute_s24(gint32 * destination,gint32 * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)186 ags_phase_shift_util_compute_s24(gint32 *destination,
187 				 gint32 *source,
188 				 guint buffer_length,
189 				 guint samplerate,
190 				 gdouble frequency,
191 				 gdouble amount,
192 				 gdouble phase)
193 {
194   gdouble freq_period, amount_period;
195   gdouble phase_period;
196   gdouble phase_shift;
197   guint i;
198 
199   if(destination == NULL ||
200      source == NULL ||
201      buffer_length == 0){
202     return;
203   }
204 
205   freq_period = samplerate / frequency;
206 
207   amount_period = (amount / (2.0 * M_PI)) * freq_period;
208 
209   phase_period = (phase / (2.0 * M_PI)) * freq_period;
210 
211   for(i = 0; i < buffer_length; i++){
212     phase_shift = ((amount / (2.0 * M_PI)) * (0x7fffff / 2.0)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
213 
214     destination[i] = 0.5 * (phase_shift + source[i]);
215   }
216 }
217 
218 /**
219  * ags_phase_shift_util_compute_s32:
220  * @destination: the destination audio buffer
221  * @source: the source audio buffer
222  * @buffer_length: the audio buffer's length
223  * @samplerate: the samplerate
224  * @frequency: the frequency
225  * @amount: the amount
226  * @phase: the phase
227  *
228  * Compute phase shift of audio buffer at @frequency with @amount with
229  * max radian 2 * M_PI.
230  *
231  * Since: 3.8.0
232  */
233 void
ags_phase_shift_util_compute_s32(gint32 * destination,gint32 * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)234 ags_phase_shift_util_compute_s32(gint32 *destination,
235 				 gint32 *source,
236 				 guint buffer_length,
237 				 guint samplerate,
238 				 gdouble frequency,
239 				 gdouble amount,
240 				 gdouble phase)
241 {
242   gdouble freq_period, amount_period;
243   gdouble phase_period;
244   gdouble phase_shift;
245   guint i;
246 
247   if(destination == NULL ||
248      source == NULL ||
249      buffer_length == 0){
250     return;
251   }
252 
253   freq_period = samplerate / frequency;
254 
255   amount_period = (amount / (2.0 * M_PI)) * freq_period;
256 
257   phase_period = (phase / (2.0 * M_PI)) * freq_period;
258 
259   for(i = 0; i < buffer_length; i++){
260     phase_shift = ((amount / (2.0 * M_PI)) * (G_MAXINT32 / 2.0)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
261 
262     destination[i] = 0.5 * (phase_shift + source[i]);
263   }
264 }
265 
266 /**
267  * ags_phase_shift_util_compute_s64:
268  * @destination: the destination audio buffer
269  * @source: the source audio buffer
270  * @buffer_length: the audio buffer's length
271  * @samplerate: the samplerate
272  * @frequency: the frequency
273  * @amount: the amount
274  * @phase: the phase
275  *
276  * Compute phase shift of audio buffer at @frequency with @amount with
277  * max radian 2 * M_PI.
278  *
279  * Since: 3.8.0
280  */
281 void
ags_phase_shift_util_compute_s64(gint64 * destination,gint64 * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)282 ags_phase_shift_util_compute_s64(gint64 *destination,
283 				 gint64 *source,
284 				 guint buffer_length,
285 				 guint samplerate,
286 				 gdouble frequency,
287 				 gdouble amount,
288 				 gdouble phase)
289 {
290   gdouble freq_period, amount_period;
291   gdouble phase_period;
292   gdouble phase_shift;
293   guint i;
294 
295   if(destination == NULL ||
296      source == NULL ||
297      buffer_length == 0){
298     return;
299   }
300 
301   freq_period = samplerate / frequency;
302 
303   amount_period = (amount / (2.0 * M_PI)) * freq_period;
304 
305   phase_period = (phase / (2.0 * M_PI)) * freq_period;
306 
307   for(i = 0; i < buffer_length; i++){
308     phase_shift = ((amount / (2.0 * M_PI)) * (G_MAXINT64 / 2.0)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
309 
310     destination[i] = 0.5 * (phase_shift + source[i]);
311   }
312 }
313 
314 /**
315  * ags_phase_shift_util_compute_float:
316  * @destination: the destination audio buffer
317  * @source: the source audio buffer
318  * @buffer_length: the audio buffer's length
319  * @samplerate: the samplerate
320  * @frequency: the frequency
321  * @amount: the amount
322  * @phase: the phase
323  *
324  * Compute phase shift of audio buffer at @frequency with @amount with
325  * max radian 2 * M_PI.
326  *
327  * Since: 3.8.0
328  */
329 void
ags_phase_shift_util_compute_float(gfloat * destination,gfloat * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)330 ags_phase_shift_util_compute_float(gfloat *destination,
331 				   gfloat *source,
332 				   guint buffer_length,
333 				   guint samplerate,
334 				   gdouble frequency,
335 				   gdouble amount,
336 				   gdouble phase)
337 {
338   gdouble freq_period, amount_period;
339   gdouble phase_period;
340   gdouble phase_shift;
341   guint i;
342 
343   if(destination == NULL ||
344      source == NULL ||
345      buffer_length == 0){
346     return;
347   }
348 
349   freq_period = samplerate / frequency;
350 
351   amount_period = (amount / (2.0 * M_PI)) * freq_period;
352 
353   phase_period = (phase / (2.0 * M_PI)) * freq_period;
354 
355   for(i = 0; i < buffer_length; i++){
356     phase_shift = (amount / (2.0 * M_PI)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
357 
358     destination[i] = 0.5 * (phase_shift + source[i]);
359   }
360 }
361 
362 /**
363  * ags_phase_shift_util_compute_double:
364  * @destination: the destination audio buffer
365  * @source: the source audio buffer
366  * @buffer_length: the audio buffer's length
367  * @samplerate: the samplerate
368  * @frequency: the frequency
369  * @amount: the amount
370  * @phase: the phase
371  *
372  * Compute phase shift of audio buffer at @frequency with @amount with
373  * max radian 2 * M_PI.
374  *
375  * Since: 3.8.0
376  */
377 void
ags_phase_shift_util_compute_double(gdouble * destination,gdouble * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)378 ags_phase_shift_util_compute_double(gdouble *destination,
379 				    gdouble *source,
380 				    guint buffer_length,
381 				    guint samplerate,
382 				    gdouble frequency,
383 				    gdouble amount,
384 				    gdouble phase)
385 {
386   gdouble y_translate;
387   gdouble freq_period, amount_period;
388   gdouble phase_period;
389   gdouble phase_shift;
390   guint i;
391 
392   if(destination == NULL ||
393      source == NULL ||
394      buffer_length == 0){
395     return;
396   }
397 
398   y_translate = -0.75;
399 
400   freq_period = samplerate / frequency;
401 
402   amount_period = (amount / (2.0 * M_PI)) * freq_period;
403 
404   phase_period = (phase / (2.0 * M_PI)) * freq_period;
405 
406   for(i = 0; i < buffer_length - (guint) floor(amount_period); i++){
407     phase_shift = (amount / (2.0 * M_PI)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
408 
409     destination[i] = 0.5 * (phase_shift + source[i]);
410   }
411 }
412 
413 /**
414  * ags_phase_shift_util_compute_complex:
415  * @destination: the destination audio buffer
416  * @source: the source audio buffer
417  * @buffer_length: the audio buffer's length
418  * @samplerate: the samplerate
419  * @frequency: the frequency
420  * @amount: the amount
421  * @phase: the phase
422  *
423  * Compute phase shift of audio buffer at @frequency with @amount with
424  * max radian 2 * M_PI.
425  *
426  * Since: 3.8.0
427  */
428 void
ags_phase_shift_util_compute_complex(AgsComplex * destination,AgsComplex * source,guint buffer_length,guint samplerate,gdouble frequency,gdouble amount,gdouble phase)429 ags_phase_shift_util_compute_complex(AgsComplex *destination,
430 				     AgsComplex *source,
431 				     guint buffer_length,
432 				     guint samplerate,
433 				     gdouble frequency,
434 				     gdouble amount,
435 				     gdouble phase)
436 {
437   gdouble freq_period, amount_period;
438   gdouble phase_period;
439   gdouble phase_shift;
440   guint i;
441 
442   if(destination == NULL ||
443      source == NULL ||
444      buffer_length == 0){
445     return;
446   }
447 
448   freq_period = samplerate / frequency;
449 
450   amount_period = (amount / (2.0 * M_PI)) * freq_period;
451 
452   phase_period = (phase / (2.0 * M_PI)) * freq_period;
453 
454   for(i = 0; i < buffer_length; i++){
455     phase_shift = (amount / (2.0 * M_PI)) * ((((int) ceil(i + phase_period) % (int) ceil(freq_period)) * 2.0 * frequency / samplerate) - 1.0);
456 
457     ags_complex_set(destination + i,
458 		    0.5 * (phase_shift + ags_complex_get(source + i)));
459   }
460 }
461