1 /* 2 * Copyright (C) 2002 2003 2004 2005 2006 2007 2008 2009 2011, Magnus Hjorth 3 * 4 * This file is part of mhWaveEdit. 5 * 6 * mhWaveEdit 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 * mhWaveEdit 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 mhWaveEdit; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 22 23 /* Chunk objects represent a segment of (PCM) audio data. The Chunks gets its 24 * data from one or many Datasource objects. 25 * 26 * The Datasources that constitute the Chunk's data must all have the same 27 * format as the Chunk. 28 * 29 * The Chunks are never modified after they are created, instead all functions 30 * that modify a chunk return a new chunk with the changes, while the original 31 * chunk and its data remains intact. 32 */ 33 34 35 36 #ifndef CHUNK_H_INCLUDED 37 #define CHUNK_H_INCLUDED 38 39 #include <stdio.h> 40 #include <gtk/gtk.h> 41 42 #ifdef HAVE_LIBSNDFILE 43 #include <sndfile.h> 44 #endif 45 46 #include "datasource.h" 47 #include "statusbar.h" 48 #include "gtkfiles.h" 49 50 #define CHUNK(obj) GTK_CHECK_CAST(obj,chunk_get_type(),Chunk) 51 #define CHUNK_CLASS(class) GTK_CHECK_CLASS_CAST(class,chunk_get_type(),ChunkClass) 52 #define IS_CHUNK(obj) GTK_CHECK_TYPE(obj,chunk_get_type()) 53 54 55 typedef struct _Chunk { 56 GtkObject object; 57 58 Dataformat format; 59 60 GList *parts; /* All items should be of type DataPart */ 61 62 /* These must match the sum of the parts */ 63 off_t length; /*�Number of samples */ 64 off_t size; /* Number of bytes (should always be 65 * length*format.samplesize*format.channels) */ 66 67 guint opencount; /* For detecting missing chunk_close calls */ 68 69 } Chunk; 70 71 typedef struct _ChunkClass { 72 GtkObjectClass parent; 73 } ChunkClass; 74 75 76 typedef struct { 77 Datasource *ds; 78 off_t position; 79 off_t length; 80 } DataPart; 81 82 83 /* Data structure used for chunk_open,chunk_read etc. */ 84 typedef Chunk ChunkHandle; 85 86 87 88 89 90 typedef gpointer WriteoutID; 91 92 /* Function for outputting processed data 93 * 94 * data - The data to output 95 * length - Length of the data (must be multiples of sample size) 96 * 97 * return value - TRUE on failure, FALSE on success 98 */ 99 100 typedef gboolean (*chunk_writeout_func)(WriteoutID id, gpointer data, 101 guint length); 102 103 104 /* Type for use as callback function for chunk_filter. 105 * 106 * NOTE: These callback functions should not call any other chunk functions 107 * except the chunk_sample_get/put-functions... 108 * 109 * in - Buffer of input data 110 * sample_size - The size of the in buffer (0 means EOF) 111 * out - Function to call for outputting data. If a out function call fails, 112 * this function should fail as well. 113 * id - Parameter to send with every call to out. 114 * format - Format of input and output data. 115 * 116 * return value - TRUE on failure, FALSE on success 117 */ 118 119 typedef gboolean (*chunk_filter_proc)(void *in, guint sample_size, 120 chunk_writeout_func out_func, 121 WriteoutID id, Dataformat *format); 122 123 124 typedef gboolean (*chunk_filter_tofmt_proc)(void *in, guint sample_size, 125 chunk_writeout_func out_func, 126 WriteoutID id, 127 Dataformat *informat, 128 Dataformat *outformat); 129 130 131 /* Type for use as callback function for chunk_parse. 132 133 sample - Buffer of input data 134 sample_size - The size of the in buffer (0 means EOF) 135 chunk - The chunk being processed. 136 137 return value - Return FALSE to continue parsing, otherwise parsing stops. 138 */ 139 140 typedef gboolean (*chunk_parse_proc)(void *sample,gint sample_size, 141 Chunk *chunk); 142 143 144 145 146 147 /* Flag that decides whether tempfiles created using chunk_filter 148 * should be floating-point if the processing function outputs 149 * floating-point data. If not, the data will be converted back and 150 * written in the original Chunk's format. 151 */ 152 153 extern gboolean chunk_filter_use_floating_tempfiles; 154 155 156 /* ------------------------------ FUNCTIONS --------------------------------- */ 157 158 159 /* Note: All functions that return gboolean values return FALSE on success. */ 160 161 /* If any function fails, it will display an error message box before it 162 * returns.*/ 163 164 165 166 /* ------ Creation functions ------ */ 167 168 169 GtkType chunk_get_type(void); 170 Chunk *chunk_new_from_datasource(Datasource *ds); 171 172 /** Returns a new chunk with the same data as this chunk but assumed to be in a 173 * different sample format. 174 */ 175 Chunk *chunk_clone_df(Chunk *chunk, Dataformat *format); 176 177 178 179 180 /* Creates a silent chunk 181 format - The data format of the chunk. 182 num_samples - The length of the chunk. 183 */ 184 185 #define chunk_new_empty(format,num_samples) chunk_new_from_datasource(datasource_new_silent(format,num_samples)) 186 187 188 189 /* Same as chunk_new_empty but you specify length as number of seconds instead 190 * of samples. 191 */ 192 193 Chunk *chunk_new_silent(Dataformat *format, gfloat seconds); 194 195 196 197 /* The number of chunk objects currently in existence */ 198 199 guint chunk_alive_count(void); 200 201 202 203 204 205 206 /* ------ Saving functions ------ */ 207 208 209 210 /* Save a chunk's data into a file. 211 212 chunk - The chunk to save. 213 file - An opened file handle to save the data into. 214 bigendian - TRUE if dumped PCM data should be big-endian. 215 bar - Status bar to display progress. Must already be in progress mode. 216 */ 217 218 gboolean chunk_dump(Chunk *chunk, EFILE *file, gboolean bigendian, 219 int dither_mode, StatusBar *bar); 220 221 222 223 224 /* ------ Chunk reading functions. ------ */ 225 226 227 /* Open a chunk for reading. Returns a ChunkHandle that can be used with 228 * chunk_read and chunk_read_array. The ChunkHandle must be released using 229 * chunk_close. 230 */ 231 232 ChunkHandle *chunk_open(Chunk *chunk); 233 234 235 236 /* Read a raw multi-channel sample from the chunk. 237 handle - ChunkHandle returned by chunk_open. 238 sampleno - The sample to read. 239 buffer - The buffer to read into. Must be at least chunk->samplebytes 240 bytes long. */ 241 242 gboolean chunk_read(ChunkHandle *handle, off_t sampleno, void *buffer, 243 int dither_mode); 244 245 246 247 /* Read a floating-point multi-channel sample from the chunk 248 handle - ChunkHandle returned by chunk_open. 249 sampleno - The sample to read. 250 buffer - The buffer to read into. Must be at least channels * sizeof(sample_t) 251 bytes long. */ 252 253 gboolean chunk_read_fp(ChunkHandle *handle, off_t sampleno, sample_t *buffer, 254 int dither_mode); 255 256 257 258 /* Read an entire array of samples from the chunk. 259 260 handle - ChunkHandle returned by chunk_open 261 sampleno - The first sample to read. 262 size - The number of bytes to read. Will be rounded down to whole sample. 263 buffer - The buffer to read into 264 265 return value - The number of bytes read (0 for error) 266 */ 267 268 guint chunk_read_array(ChunkHandle *handle, off_t sampleno, guint size, 269 void *buffer, int dither_mode, off_t *clipcount); 270 271 272 273 /* Read an entire array of floating-point samples from the chunk. 274 275 handle - ChunkHandle returned by chunk_open 276 sampleno - The first sample to read. 277 samples - The number of multi-channel samples to read 278 buffer - The buffer to read into 279 280 return value - The number of multi-channel samples read (0 for error) 281 */ 282 283 guint chunk_read_array_fp(ChunkHandle *handle, off_t sampleno, guint samples, 284 sample_t *buffer, int dither_mode, off_t *clipcount); 285 286 287 /* Frees the resources used by a ChunkHandle. All handles should be freed when 288 * they're no longer in use. 289 */ 290 291 void chunk_close(ChunkHandle *handle); 292 293 294 295 296 /* ------ Chunk effects and utility functions ------- */ 297 298 /* All these functions return a new (temporary) chunk on success and NULL on 299 * failure */ 300 301 302 303 /* Creates a new chunk with the original chunks data converted into a different 304 * sample rate possibly using interpolation. */ 305 306 Chunk *chunk_convert_samplerate(Chunk *chunk, gint samplerate, 307 const gchar *rateconv_driver, 308 int dither_mode, StatusBar *bar); 309 310 Chunk *chunk_convert_speed(Chunk *chunk, gfloat speed_factor, 311 int dither_mode, StatusBar *bar); 312 313 314 /* Creates a new chunk with the original chunk's data converted into a 315 * different sample format (samplerate and channels are unchanged) */ 316 Chunk *chunk_convert_sampletype(Chunk *chunk, Dataformat *newtype); 317 318 /* Converts the chunk to any format. */ 319 Chunk *chunk_convert(Chunk *chunk, Dataformat *new_format, 320 int dither_mode, StatusBar *bar); 321 322 Chunk *chunk_byteswap(Chunk *chunk); 323 324 /* Creates a new chunk with the original chunk's data but with one channel 325 * removed. */ 326 327 Chunk *chunk_remove_channel(Chunk *chunk, gint channel, StatusBar *bar); 328 329 330 331 /* Creates a new chunk with the original chunk's data but with an extra channel 332 * inserted containing a copy of another channel's data. */ 333 334 Chunk *chunk_copy_channel(Chunk *chunk, gint channel, int dither_mode, 335 StatusBar *bar); 336 337 338 339 /* Creates a new chunk with the original chunk's data mixed into one channel. */ 340 341 Chunk *chunk_onechannel(Chunk *chunk, int dither_mode, StatusBar *bar); 342 343 /* Creates a new Chunk with the original chunk's data, but with the 344 * last channels removed or silent channels added so the channel count 345 * becomes new_channels */ 346 Chunk *chunk_convert_channels(Chunk *chunk, guint new_channels); 347 348 349 350 351 /* Creates a new Chunk with a mix of the original chunk's channels. 352 * channels_out determines the number of output channels 353 * map is a (chunk->channels x channels_out)-matrix; 354 * If map[src*channels_out + dst], then channel <src> from chunk will be 355 * copied into channel <dst> of the result. Output channels with no assigned 356 * inputs will be silent, output channels with more than one assigned input 357 * will be mixed. 358 */ 359 Chunk *chunk_remap_channels(Chunk *chunk, int channels_out, gboolean *map, 360 int dither_mode, StatusBar *bar); 361 362 /* Creates a new chunk containing a mix of two chunk's data. The chunks must 363 * have the same format but need not be of the same length. */ 364 365 Chunk *chunk_mix(Chunk *c1, Chunk *c2, int dither_mode, StatusBar *bar); 366 367 /* Creates a new Chunk with a channel count of the sum of c1 and c2:s channel 368 * counts, having the data from Chunk c1 in the first channels, and 369 * the data from Chunk c2 in the following channels. 370 * 371 * The data is aligned in time, so that the sample in c1 at 372 * c1_align_point coincides with the sample in c2 at 373 * c2_align_point. The point in the resulting chunk where this sample 374 * exists is stored in *align_point_out. 375 */ 376 377 Chunk *chunk_sandwich(Chunk *c1, Chunk *c2, 378 off_t c1_align_point, off_t c2_align_point, 379 off_t *align_point_out, 380 int dither_mode, StatusBar *bar); 381 382 383 off_t chunk_zero_crossing_any_forward( 384 Chunk *c, StatusBar *bar, off_t cursorpos); 385 off_t chunk_zero_crossing_any_reverse( 386 Chunk *c, StatusBar *bar, off_t cursorpos); 387 off_t chunk_zero_crossing_all_forward( 388 Chunk *c, StatusBar *bar, off_t cursorpos); 389 off_t chunk_zero_crossing_all_reverse( 390 Chunk *c, StatusBar *bar, off_t cursorpos); 391 392 393 /* Returns the maximum absolute value of all the samples in the chunk. 394 * Returns negative value if anything failed. */ 395 396 sample_t chunk_peak_level(Chunk *c, StatusBar *bar); 397 398 399 400 401 /* Returns a new chunk with all samples of the chunk c multiplied by a 402 * factor. */ 403 404 Chunk *chunk_amplify(Chunk *c, sample_t factor, int dither_mode, 405 StatusBar *bar); 406 407 408 409 /* Creates a new chunk with all samples of the chunk c multiplied by a factor 410 * varying from start_factor to end_factor 411 */ 412 Chunk *chunk_volume_ramp(Chunk *c, sample_t start_factor, sample_t end_factor, 413 int dither_mode, StatusBar *bar); 414 415 /* Create a new chunk consisting of one chunk's data followed by another 416 * chunk's data. Always succeeds. 417 */ 418 419 Chunk *chunk_append(Chunk *first, Chunk *second); 420 421 422 423 /* Create a new chunk of the same length and format as the input chunk, 424 * consisting of a linear interpolation between the input chunk's two 425 * endpoints. Returns NULL on failure. 426 * 427 * If falldown_mode is TRUE and the chunk is long, the endpoints will 428 *be ramped down to zero and the middle part will be constant zero. 429 */ 430 431 Chunk *chunk_interpolate_endpoints(Chunk *chunk, gboolean falldown_mode, 432 int dither_mode, StatusBar *bar); 433 434 435 436 /* Creates a new chunk with the original chunk's data and another chunk's data 437 * inserted at a certain offset (offset must be at an even sample) */ 438 439 Chunk *chunk_insert(Chunk *chunk, Chunk *part, off_t position); 440 441 /* Returns a chunk containing a part of the original chunk's data */ 442 443 Chunk *chunk_get_part(Chunk *chunk, off_t start, off_t length); 444 445 /* These functions return a new chunk where a part of the original chunk's 446 * data has been removed or replaced by the data of another chunk. 447 */ 448 449 Chunk *chunk_remove_part(Chunk *chunk, off_t start, off_t length); 450 Chunk *chunk_replace_part(Chunk *chunk, off_t start, off_t length, Chunk *new); 451 452 453 454 /* ------ Processing functions ------ */ 455 456 457 /* Pipe a chunk's contents through a callback function and create a new chunk 458 * with the output. 459 * 460 * chunk - The chunk to process 461 * proc - The callback function (see declaration of chunk_filter_proc above) 462 * eof_proc - If this argument is non-NULL, when all data has been filtered 463 * through proc, this function will be called with sample_size==0 to produce 464 * the last data. This argument is usually either NULL or the same as proc. 465 * amount - How much should be sent each time. One of: 466 * CHUNK_FILTER_ONE - One sample value at a time 467 * CHUNK_FILTER_FULL - One multichannel sample at a time 468 * CHUNK_FILTER_MANY - Many multichannel samples at a time. The callback 469 * function can determine the exact amount by looking at the 470 * sample_size parameter. 471 * 472 * must_convert - If TRUE the in and out buffer will always be in 473 * sample_t format instead of the chunk's native sample format. 474 * bar - Status bar to display progress in 475 * title - Title to display in status bar. 476 * returns - The output or NULL on failure. 477 */ 478 479 #define CHUNK_FILTER_ONE 0 480 #define CHUNK_FILTER_FULL 1 481 #define CHUNK_FILTER_MANY 2 482 483 Chunk *chunk_filter(Chunk *chunk, chunk_filter_proc proc, 484 chunk_filter_proc eof_proc, gint amount, 485 gboolean must_convert, int dither_mode, 486 StatusBar *bar, gchar *title); 487 488 Chunk *chunk_filter_tofmt(Chunk *chunk, chunk_filter_tofmt_proc proc, 489 chunk_filter_tofmt_proc eof_proc, gint amount, 490 gboolean must_convert, Dataformat *tofmt, 491 int dither_mode, 492 StatusBar *bar, gchar *title); 493 494 /* Send a chunk's contents one sample at a time to a callback function. 495 * 496 * chunk - The chunk to process. 497 * proc - The callback function (see definition of chunk_parse_proc above). 498 * allchannels - If TRUE the samples will be sent with all channels' data at 499 * the same time, if FALSE one channel at a time will be sent. 500 * convert - If TRUE the samples will be sent as sample_t (floating point) 501 * values, otherwise they will be sent in raw format. 502 * samplepos - The location within the chunk that parsing should start at. 503 * reverse - If TRUE, parsing will move backward through the chunk; if FALSE 504 * parsing will move forward through the chunk. 505 * 506 * returns - FALSE on success, TRUE if proc returned TRUE or a read error 507 * occured. 508 */ 509 510 gboolean chunk_parse(Chunk *chunk, chunk_parse_proc proc, gboolean allchannels, 511 gboolean convert, int dither_mode, 512 StatusBar *bar, gchar *title, off_t samplepos, gboolean reverse); 513 514 515 516 /* ------ Miscellaneous chunk functions ------ */ 517 518 519 520 /* Determines whether the format parameters of two chunks are the same. 521 * To return TRUE, the chunks must have the same samplerate, samplesize, 522 * channels and sign. */ 523 524 #define chunk_format_equal(c1,c2) dataformat_equal(&(c1->format),&(c2->format)) 525 526 527 528 #define chunk_get_time(c,s,t) get_time((c)->format.samplerate,s,s,t,default_time_mode) 529 530 531 532 /* Calls func for each existing chunk. */ 533 void chunk_foreach(GFunc func, gpointer user_data); 534 535 gboolean clipwarn(off_t clipcount, gboolean maycancel); 536 537 538 #endif 539