1 /*
2 * Sweep, a sound wave editor.
3 *
4 * Copyright (C) 2000 Conrad Parker
5 *
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <glib.h>
28
29 #if 0
30 #include <unistd.h>
31 #include <sys/mman.h>
32 #endif
33
34 #include <sweep/sweep_types.h>
35 #include <sweep/sweep_typeconvert.h>
36 #include <sweep/sweep_selection.h>
37 #include <sweep/sweep_undo.h>
38
39 #include "edit.h"
40 #include "format.h"
41 #include "view.h"
42 #include "sample-display.h"
43 #include "driver.h"
44
45 sw_sounddata *
sounddata_new_empty(gint nr_channels,gint sample_rate,gint sample_length)46 sounddata_new_empty(gint nr_channels, gint sample_rate, gint sample_length)
47 {
48 sw_sounddata *s;
49 sw_framecount_t len;
50
51 s = g_malloc (sizeof(sw_sounddata));
52 if (!s)
53 return NULL;
54
55 s->refcount = 1;
56
57 s->format = format_new (nr_channels, sample_rate);
58
59 s->nr_frames = (sw_framecount_t) sample_length;
60
61 if (sample_length > 0) {
62 len = frames_to_bytes (s->format, sample_length);
63
64 #if 1
65 s->data = g_malloc0 ((size_t)len);
66 #else
67 s->data = sweep_large_alloc_zero (len, PROT_READ|PROT_WRITE);
68 #endif
69
70
71 if (!(s->data)) {
72 #if 0
73 #if (SIZEOF_OFF_T == 8)
74 fprintf(stderr, "Unable to allocate %lld bytes for sample data.\n", len);
75 #else
76 fprintf(stderr, "Unable to allocate %d bytes for sample data.\n", len);
77 #endif
78 #else
79 fprintf(stderr, "Unable to allocate %d bytes for sample data.\n", len);
80 #endif
81 g_free(s);
82 return NULL;
83 #ifdef DEBUG
84 } else {
85 g_print ("g_malloc0'd %d bytes for new sounddata\n", len);
86 #endif
87 }
88 } else {
89 s->data = NULL;
90 }
91
92 s->sels = NULL;
93 s->sels_mutex = g_mutex_new();
94 s->data_mutex = g_mutex_new();
95
96 return s;
97 }
98
99 void
sounddata_clear_selection(sw_sounddata * sounddata)100 sounddata_clear_selection (sw_sounddata * sounddata)
101 {
102 GList * gl;
103 sw_sel * sel;
104
105 for (gl = sounddata->sels; gl; gl = gl->next){
106 sel = (sw_sel*)gl->data;
107 sel_free(sel);
108 }
109
110 g_list_free(sounddata->sels);
111
112 sounddata->sels = NULL;
113 };
114
115 void
sounddata_destroy(sw_sounddata * sounddata)116 sounddata_destroy (sw_sounddata * sounddata)
117 {
118 /*size_t len;*/
119
120 sounddata->refcount--;
121
122 if (sounddata->refcount <= 0) {
123 #if 1
124 g_free (sounddata->data);
125 #else
126 len = frames_to_bytes (sounddata->format, sounddata->nr_frames);
127 munmap (sounddata->data, len);
128 #endif
129 sounddata_clear_selection (sounddata);
130 g_free (sounddata);
131 g_mutex_free(sounddata->data_mutex);
132 }
133 }
134
135 void
sounddata_lock_selection(sw_sounddata * sounddata)136 sounddata_lock_selection (sw_sounddata * sounddata)
137 {
138 g_mutex_lock (sounddata->sels_mutex);
139 }
140
141 void
sounddata_unlock_selection(sw_sounddata * sounddata)142 sounddata_unlock_selection (sw_sounddata * sounddata)
143 {
144 g_mutex_unlock (sounddata->sels_mutex);
145 }
146
147 guint
sounddata_selection_nr_regions(sw_sounddata * sounddata)148 sounddata_selection_nr_regions (sw_sounddata * sounddata)
149 {
150 return g_list_length (sounddata->sels);
151 }
152
153 static gint
sounddata_sel_needs_normalising(sw_sounddata * sounddata)154 sounddata_sel_needs_normalising (sw_sounddata *sounddata)
155 {
156 GList * gl;
157 sw_sel * osel = NULL, * sel;
158 sw_framecount_t nr_frames;
159
160 if(!sounddata->sels) return FALSE;
161
162 nr_frames = sounddata->nr_frames;
163
164 /* Seed osel with 'fake' iteration of following loop */
165 gl = sounddata->sels;
166 osel = (sw_sel *)gl->data;
167 if (osel->sel_start < 0 || osel->sel_end > nr_frames)
168 return TRUE;
169
170 gl = gl->next;
171 for(; gl; gl = gl->next) {
172 sel = (sw_sel *)gl->data;
173
174 if (sel->sel_start < 0 || sel->sel_end > nr_frames)
175 return TRUE;
176
177 if(osel->sel_end >= sel->sel_start) {
178 return TRUE;
179 }
180
181 if(osel->sel_end < sel->sel_end) {
182 osel = sel;
183 }
184 }
185
186 return FALSE;
187 }
188
189 /*
190 * sounddata_normalise_selection(sounddata)
191 *
192 * normalise the selection of sounddata, ie. make sure there's
193 * no overlaps and merge adjoining sections.
194 */
195
196 void
sounddata_normalise_selection(sw_sounddata * sounddata)197 sounddata_normalise_selection (sw_sounddata * sounddata)
198 {
199 GList * gl;
200 GList * nsels = NULL;
201 sw_sel * osel = NULL, * sel;
202 sw_framecount_t nr_frames;
203
204 if (!sounddata_sel_needs_normalising(sounddata)) return;
205
206 nr_frames = sounddata->nr_frames;
207
208 /* Seed osel with 'fake' iteration of following loop */
209 gl = sounddata->sels;
210 sel = (sw_sel *)gl->data;
211 sel->sel_start = CLAMP(sel->sel_start, 0, nr_frames);
212 sel->sel_end = CLAMP(sel->sel_end, 0, nr_frames);
213
214 osel = sel_copy(sel);
215
216 gl = gl->next;
217
218 for (; gl; gl = gl->next) {
219 sel = (sw_sel *)gl->data;
220 sel->sel_start = CLAMP(sel->sel_start, 0, nr_frames);
221 sel->sel_end = CLAMP(sel->sel_end, 0, nr_frames);
222
223 /* Check for an overlap */
224 if(osel->sel_end >= sel->sel_start) {
225
226 /* If sel is completely contained in osel, ignore it. */
227 if(osel->sel_end > sel->sel_end) {
228 continue;
229 }
230
231 /* Set: osel = osel INTERSECT sel
232 * we already know osel->sel_start <= sel->sel_start */
233 osel->sel_end = sel->sel_end;
234
235 } else {
236 /* No more overlaps with osel; insert it in nsels, and
237 * reset osel. */
238 if (osel->sel_start == osel->sel_end) {
239 g_free (osel);
240 } else {
241 nsels = g_list_insert_sorted(nsels, osel, (GCompareFunc)sel_cmp);
242 }
243 osel = sel_copy(sel);
244 }
245 }
246
247 /* Insert the last created osel */
248 if (osel->sel_start == osel->sel_end) {
249 g_free (osel);
250 } else {
251 nsels = g_list_insert_sorted(nsels, osel, (GCompareFunc)sel_cmp);
252 }
253
254 /* Clear the old selection */
255 sounddata_clear_selection (sounddata);
256
257 /* Set the newly created (normalised) selection */
258 sounddata->sels = nsels;
259
260 }
261
262 void
sounddata_add_selection(sw_sounddata * sounddata,sw_sel * sel)263 sounddata_add_selection (sw_sounddata * sounddata, sw_sel * sel)
264 {
265 sounddata->sels =
266 g_list_insert_sorted(sounddata->sels, sel, (GCompareFunc)sel_cmp);
267 }
268
269 sw_sel *
sounddata_add_selection_1(sw_sounddata * sounddata,sw_framecount_t start,sw_framecount_t end)270 sounddata_add_selection_1 (sw_sounddata * sounddata, sw_framecount_t start, sw_framecount_t end)
271 {
272 sw_sel * sel;
273
274 sel = sel_new (start, end);
275
276 sounddata_add_selection(sounddata, sel);
277
278 return sel;
279 }
280
281 sw_sel *
sounddata_set_selection_1(sw_sounddata * sounddata,sw_framecount_t start,sw_framecount_t end)282 sounddata_set_selection_1 (sw_sounddata * sounddata, sw_framecount_t start, sw_framecount_t end)
283 {
284 sounddata_clear_selection (sounddata);
285
286 return sounddata_add_selection_1 (sounddata, start, end);
287 }
288
289 gint
sounddata_selection_nr_frames(sw_sounddata * sounddata)290 sounddata_selection_nr_frames (sw_sounddata * sounddata)
291 {
292 gint nr_frames = 0;
293 GList * gl;
294 sw_sel * sel;
295
296 for (gl = sounddata->sels; gl; gl = gl->next) {
297 sel = (sw_sel *)gl->data;
298
299 nr_frames += sel->sel_end - sel->sel_start;
300 }
301
302 return nr_frames;
303 }
304
305 sw_framecount_t
sounddata_selection_width(sw_sounddata * sounddata)306 sounddata_selection_width (sw_sounddata * sounddata)
307 {
308 GList * gl;
309 sw_sel * sel;
310 sw_framecount_t start, end;
311
312 if ((gl = sounddata->sels) == NULL) return 0;
313 sel = (sw_sel *)gl->data;
314 start = sel->sel_start;
315
316 gl = g_list_last (sounddata->sels);
317 sel = (sw_sel *)gl->data;
318 end = sel->sel_end;
319
320 return (end - start);
321 }
322
323 void
sounddata_selection_translate(sw_sounddata * sounddata,gint delta)324 sounddata_selection_translate (sw_sounddata * sounddata, gint delta)
325 {
326 GList * gl;
327 sw_sel * sel;
328
329 for (gl = sounddata->sels; gl; gl = gl->next) {
330 sel = (sw_sel *)gl->data;
331
332 sel->sel_start += delta;
333 sel->sel_end += delta;
334 }
335
336 /* XXX: Crop any regions outside of [0, nr_frames] */
337 sounddata_normalise_selection (sounddata);
338 }
339
340 void
sounddata_selection_scale(sw_sounddata * sounddata,gfloat scale)341 sounddata_selection_scale (sw_sounddata * sounddata, gfloat scale)
342 {
343 GList * gl;
344 sw_sel * sel;
345 sw_framecount_t sels_start;
346
347 if ((gl = sounddata->sels) == NULL) return;
348
349 sel = (sw_sel *)gl->data;
350 sels_start = sel->sel_start;
351
352 for (gl = sounddata->sels; gl; gl = gl->next) {
353 sel = (sw_sel *)gl->data;
354
355 sel->sel_start = sels_start + ((sel->sel_start - sels_start) * scale);
356 sel->sel_end = sels_start + ((sel->sel_end - sels_start) * scale);
357 }
358
359 /* XXX: Crop any regions outside of [0, nr_frames] */
360 sounddata_normalise_selection (sounddata);
361 }
362
363 /*
364 * sounddata_copyin_selection (sounddata1, sounddata2)
365 *
366 * copies the selection of sounddata1 into sounddata2. If sounddata2 previously
367 * had a selection, the two are merged.
368 */
369 void
sounddata_copyin_selection(sw_sounddata * sounddata1,sw_sounddata * sounddata2)370 sounddata_copyin_selection (sw_sounddata * sounddata1, sw_sounddata * sounddata2)
371 {
372 GList * gl;
373 sw_sel * sel, *sel2;
374
375 for (gl = sounddata1->sels; gl; gl = gl->next) {
376 sel = (sw_sel *)gl->data;
377
378 sel2 = sel_copy (sel);
379 sounddata_add_selection (sounddata2, sel2);
380 }
381
382 sounddata_normalise_selection (sounddata2);
383 }
384