5 #include "filesndfile.h"
9 #define _(String) gettext(String)
10 #define gettext_noop(String) String
11 #define N_(String) gettext_noop (String)
13 #ifdef HAVE_LIBSNDFILE_0
14 // Routines for libsndfile 0.x.x
16 FileSndFile::FileSndFile(Asset *asset, File *file)
17 : FileBase(asset, file)
24 FileSndFile::~FileSndFile()
26 if(temp_double) delete [] temp_double;
29 int FileSndFile::check_sig(Asset *asset)
31 //printf("FileSndFile::check_sig 1\n");
35 //printf("FileSndFile::check_sig 1\n");
36 SNDFILE *fd = sf_open_read(asset->path, &fd_config);
37 //printf("FileSndFile::check_sig 1 %p\n", fd);
46 //printf("FileSndFile::check_sig 2\n");
50 void FileSndFile::asset_to_format()
54 case FILE_PCM: fd_config.format = SF_FORMAT_RAW; break;
55 case FILE_WAV: fd_config.format = SF_FORMAT_WAV; break;
56 case FILE_AU: fd_config.format = SF_FORMAT_AU; break;
57 case FILE_AIFF: fd_config.format = SF_FORMAT_AIFF; break;
60 // Not all of these are allowed in all sound formats.
61 // Raw can't be float.
67 if(asset->format != FILE_PCM)
69 fd_config.format |= SF_FORMAT_PCM;
74 fd_config.format |= SF_FORMAT_PCM_LE;
76 fd_config.format |= SF_FORMAT_PCM_BE;
78 fd_config.pcmbitwidth = asset->bits;
79 //printf("FileSndFile::asset_to_format 1 %x %d\n", fd_config.format, fd_config.pcmbitwidth);
83 fd_config.format |= SF_FORMAT_ULAW;
84 fd_config.pcmbitwidth = 16;
88 //printf("FileSndFile::asset_to_format 1\n");
89 fd_config.format |= SF_FORMAT_FLOAT;
90 fd_config.pcmbitwidth = 16;
94 if(fd_config.format == FILE_WAV)
95 fd_config.format |= SF_FORMAT_MS_ADPCM;
97 fd_config.format |= SF_FORMAT_IMA_ADPCM;
98 fd_config.pcmbitwidth = 16;
102 fd_config.seekable = 1;
103 fd_config.samplerate = asset->sample_rate;
104 fd_config.channels = asset->channels;
105 //printf("FileSndFile::asset_to_format %x %d %d\n", fd_config.format, fd_config.pcmbitwidth, fd_config.channels);
108 void FileSndFile::format_to_asset()
110 //printf("FileSndFile::format_to_asset 1\n");
111 asset->byte_order = 0;
114 if(asset->format == 0)
115 switch(fd_config.format & SF_FORMAT_TYPEMASK)
118 asset->format = FILE_WAV;
119 asset->byte_order = 1;
122 case SF_FORMAT_AIFF: asset->format = FILE_AIFF; break;
123 case SF_FORMAT_AU: asset->format = FILE_AU; break;
124 case SF_FORMAT_AULE: asset->format = FILE_AU; break;
125 case SF_FORMAT_RAW: asset->format = FILE_PCM; break;
126 case SF_FORMAT_PAF: asset->format = FILE_SND; break;
127 case SF_FORMAT_SVX: asset->format = FILE_SND; break;
128 case SF_FORMAT_NIST: asset->format = FILE_SND; break;
131 switch(fd_config.format & SF_FORMAT_SUBMASK)
133 case SF_FORMAT_FLOAT:
134 asset->bits = BITSFLOAT;
137 asset->bits = BITSULAW;
139 case SF_FORMAT_IMA_ADPCM:
140 case SF_FORMAT_MS_ADPCM:
141 asset->bits = BITS_ADPCM;
144 asset->bits = fd_config.pcmbitwidth;
146 case SF_FORMAT_PCM_BE:
147 asset->byte_order = 0;
148 asset->bits = fd_config.pcmbitwidth;
150 case SF_FORMAT_PCM_LE:
151 asset->byte_order = 1;
152 asset->bits = fd_config.pcmbitwidth;
154 case SF_FORMAT_PCM_S8:
156 asset->bits = BITSLINEAR8;
158 case SF_FORMAT_PCM_U8:
160 asset->bits = BITSLINEAR8;
164 asset->audio_data = 1;
165 asset->audio_length = fd_config.samples;
166 if(!asset->sample_rate)
167 asset->sample_rate = fd_config.samplerate;
168 asset->channels = fd_config.channels;
169 //printf("FileSndFile::format_to_asset %x %d %d %x\n", fd_config.format & SF_FORMAT_TYPEMASK, fd_config.pcmbitwidth, fd_config.samples, fd_config.format & SF_FORMAT_SUBMASK);
173 int FileSndFile::open_file(int rd, int wr)
181 if(asset->format == FILE_PCM)
184 fd = sf_open_read(asset->path, &fd_config);
189 fd = sf_open_read(asset->path, &fd_config);
190 // Doesn't calculate the length
197 //printf("FileSndFile::open_file 1\n");
199 //printf("FileSndFile::open_file 1\n");
200 fd = sf_open_write(asset->path, &fd_config);
201 //printf("FileSndFile::open_file 2 %p\n", fd);
207 printf("FileSndFile::open_file:\n");
214 int FileSndFile::close_file()
216 //printf("FileSndFile::close_file 1\n");
218 FileBase::close_file();
219 fd_config.format = 0;
223 int FileSndFile::set_audio_position(int64_t sample)
225 //printf("FileSndFile::set_audio_position %ld\n", sample);
226 // Commented out /* && psf->dataoffset */ in sndfile.c: 761
227 if(sf_seek(fd, sample, SEEK_SET) < 0)
229 printf("FileSndFile::set_audio_position %lld: failed\n", sample);
236 int FileSndFile::read_samples(double *buffer, int64_t len)
240 // Get temp buffer for interleaved channels
241 if(len <= 0 || len > 1000000)
242 printf("FileSndFile::read_samples len=%d\n", len);
245 printf("FileSndFile::read_samples buffer=%p\n", buffer);
247 //printf("FileSndFile::read_samples 1 current_sample=%d len=%d\n", file->current_sample, len);
248 if(temp_allocated && temp_allocated < len)
250 //printf("FileSndFile::read_samples 1\n");
251 delete [] temp_double;
258 temp_allocated = len;
259 //printf("FileSndFile::read_samples 2\n");
260 temp_double = new double[len * asset->channels];
263 //printf("FileSndFile::read_samples 3\n");
264 result = !sf_read_double(fd, temp_double, len * asset->channels, 1);
265 //printf("FileSndFile::read_samples 4\n");
268 printf("FileSndFile::read_samples fd=%p temp_double=%p len=%d asset=%p asset->channels=%d\n",
269 fd, temp_double, len, asset, asset->channels);
271 //printf("FileSndFile::read_samples 4\n");
272 // Extract single channel
273 for(int i = 0, j = file->current_channel;
275 i++, j += asset->channels)
277 buffer[i] = temp_double[j];
279 //printf("FileSndFile::read_samples 6\n");
284 int FileSndFile::write_samples(double **buffer, int64_t len)
288 // Get temp buffer for interleaved channels
289 //printf("FileSndFile::read_samples 1\n");
290 if(temp_allocated && temp_allocated < len)
293 delete [] temp_double;
297 //printf("FileSndFile::read_samples 2\n");
300 temp_allocated = len;
301 temp_double = new double[len * asset->channels];
304 // Interleave channels
305 for(int i = 0; i < asset->channels; i++)
307 for(int j = 0; j < len; j++)
309 double sample = buffer[i][j];
310 // Libsndfile does not limit values
311 //if(sample > 1.0 || sample < -1.0) printf("FileSndFile::write_samples %f\n", sample);
312 CLAMP(sample, -1.0, (32767.0 / 32768.0));
313 temp_double[j * asset->channels + i] = sample;
317 result = !sf_writef_double(fd, temp_double, len, 1);
322 void FileSndFile::get_parameters(BC_WindowBase *parent_window,
324 BC_WindowBase* &format_window,
330 SndFileConfig *window = new SndFileConfig(parent_window, asset);
331 format_window = window;
332 window->create_objects();
333 window->run_window();
338 SndFileConfig::SndFileConfig(BC_WindowBase *parent_window, Asset *asset)
339 : BC_Window(PROGRAM_NAME ": Audio Compression",
340 parent_window->get_abs_cursor_x(),
341 parent_window->get_abs_cursor_y(),
345 this->parent_window = parent_window;
349 SndFileConfig::~SndFileConfig()
351 if(bits_popup) delete bits_popup;
353 int SndFileConfig::create_objects()
358 switch(asset->format)
363 add_tool(new BC_Title(x, y, _("Compression:")));
365 if(asset->format == FILE_WAV)
366 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 1, 1, 0);
368 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
370 bits_popup->create_objects();
375 if(asset->format != FILE_AU)
376 add_subwindow(new BC_CheckBox(x, y, &asset->dither, _("Dither")));
378 if(asset->format == FILE_PCM)
380 add_subwindow(new BC_CheckBox(x, y, &asset->signed_, _("Signed")));
382 add_subwindow(new BC_Title(x, y, _("Byte order:")));
383 add_subwindow(hilo = new SndFileHILO(this, x + 100, y));
384 add_subwindow(lohi = new SndFileLOHI(this, x + 170, y));
386 add_subwindow(new BC_OKButton(this));
390 int SndFileConfig::close_event()
398 SndFileHILO::SndFileHILO(SndFileConfig *gui, int x, int y)
399 : BC_Radial(x, y, gui->asset->byte_order == 0, _("Hi Lo"))
403 int SndFileHILO::handle_event()
405 gui->asset->byte_order = 0;
406 gui->lohi->update(0);
413 SndFileLOHI::SndFileLOHI(SndFileConfig *gui, int x, int y)
414 : BC_Radial(x, y, gui->asset->byte_order == 1, _("Lo Hi"))
418 int SndFileLOHI::handle_event()
420 gui->asset->byte_order = 1;
421 gui->hilo->update(0);
424 #else // #ifdef HAVE_LIBSNDFILE_0
425 // Updated, libsndfile 1.x.x compatible routines
427 FileSndFile::FileSndFile(Asset *asset, File *file)
428 : FileBase(asset, file)
432 fd_config.format = 0;
435 FileSndFile::~FileSndFile()
437 if(temp_double) delete [] temp_double;
440 int FileSndFile::check_sig(Asset *asset)
442 //printf("FileSndFile::check_sig 1\n");
445 fd_config.format = 0;
446 //printf("FileSndFile::check_sig 1\n");
447 SNDFILE *fd = sf_open(asset->path, SFM_READ, &fd_config);
448 //printf("FileSndFile::check_sig 1\n");
457 //printf("FileSndFile::check_sig 2\n");
461 void FileSndFile::asset_to_format()
463 // Set the file format
464 switch(asset->format)
466 case FILE_PCM: fd_config.format = SF_FORMAT_RAW; break;
467 case FILE_WAV: fd_config.format = SF_FORMAT_WAV; break;
468 case FILE_AU: fd_config.format = SF_FORMAT_AU; break;
469 case FILE_AIFF: fd_config.format = SF_FORMAT_AIFF; break;
472 // Set the coding format - not all file/coding format combinations
479 fd_config.format |= SF_FORMAT_PCM_S8;
483 fd_config.format |= SF_FORMAT_PCM_U8;
488 fd_config.format |= SF_FORMAT_PCM_16;
492 fd_config.format |= SF_FORMAT_PCM_24;
496 // RAW can't be float
497 if (asset->format != FILE_PCM)
499 fd_config.format |= SF_FORMAT_FLOAT;
504 // FIXME: can RAW be ADPCM?
505 fd_config.format |= SF_FORMAT_ULAW;
509 // FIXME: can RAW be ADPCM?
510 if(fd_config.format == FILE_WAV)
512 fd_config.format |= SF_FORMAT_MS_ADPCM;
516 fd_config.format |= SF_FORMAT_IMA_ADPCM;
521 if(asset->byte_order)
523 fd_config.format |= SF_ENDIAN_LITTLE;
527 fd_config.format |= SF_ENDIAN_BIG;
530 fd_config.seekable = 1;
531 fd_config.samplerate = asset->sample_rate;
532 fd_config.channels = asset->channels;
535 void FileSndFile::format_to_asset()
537 //printf("FileSndFile::format_to_asset 1\n");
538 asset->byte_order = 0;
541 if(asset->format == 0)
543 switch(fd_config.format & SF_FORMAT_TYPEMASK)
546 asset->format = FILE_WAV;
547 asset->byte_order = 1;
550 case SF_FORMAT_AIFF: asset->format = FILE_AIFF; break;
551 case SF_FORMAT_AU: asset->format = FILE_AU; break;
552 // case SF_FORMAT_AULE: asset->format = FILE_AU; break;
553 case SF_FORMAT_RAW: asset->format = FILE_PCM; break;
554 case SF_FORMAT_PAF: asset->format = FILE_SND; break;
555 case SF_FORMAT_SVX: asset->format = FILE_SND; break;
556 case SF_FORMAT_NIST: asset->format = FILE_SND; break;
560 switch(fd_config.format & SF_FORMAT_SUBMASK)
562 case SF_FORMAT_FLOAT:
563 asset->bits = BITSFLOAT;
567 asset->bits = BITSULAW;
570 case SF_FORMAT_IMA_ADPCM:
571 case SF_FORMAT_MS_ADPCM:
572 asset->bits = BITS_ADPCM;
575 case SF_FORMAT_PCM_16:
580 case SF_FORMAT_PCM_24:
585 case SF_FORMAT_PCM_32:
590 case SF_FORMAT_PCM_S8:
592 asset->bits = BITSLINEAR8;
595 case SF_FORMAT_PCM_U8:
597 asset->bits = BITSLINEAR8;
601 switch(fd_config.format & SF_FORMAT_ENDMASK)
603 case SF_ENDIAN_LITTLE:
604 asset->byte_order = 1;
607 asset->byte_order = 0;
611 asset->audio_data = 1;
612 asset->audio_length = fd_config.frames;
614 if(!asset->sample_rate)
615 asset->sample_rate = fd_config.samplerate;
617 asset->channels = fd_config.channels;
619 //printf("FileSndFile::format_to_asset %x %d %d %x\n", fd_config.format & SF_FORMAT_TYPEMASK, fd_config.pcmbitwidth, fd_config.samples, fd_config.format & SF_FORMAT_SUBMASK);
623 int FileSndFile::open_file(int rd, int wr)
631 if(asset->format == FILE_PCM)
634 fd = sf_open(asset->path, SFM_READ, &fd_config);
639 fd = sf_open(asset->path, SFM_READ, &fd_config);
640 // Doesn't calculate the length
648 //printf("FileSndFile::open_file 1\n");
650 //printf("FileSndFile::open_file 1\n");
651 fd = sf_open(asset->path, SFM_WRITE, &fd_config);
652 //printf("FileSndFile::open_file 2 %p\n", fd);
659 printf("FileSndFile::open_file:\n");
666 int FileSndFile::close_file()
668 //printf("FileSndFile::close_file 1\n");
670 FileBase::close_file();
671 fd_config.format = 0;
675 int FileSndFile::set_audio_position(int64_t sample)
677 //printf("FileSndFile::set_audio_position %ld\n", sample);
678 // Commented out /* && psf->dataoffset */ in sndfile.c: 761
679 if(sf_seek(fd, sample, SEEK_SET) < 0)
681 printf("FileSndFile::set_audio_position %ld: failed\n", sample);
688 int FileSndFile::read_samples(double *buffer, int64_t len)
692 // Get temp buffer for interleaved channels
693 if(len <= 0 || len > 1000000)
694 printf("FileSndFile::read_samples len=%d\n", len);
697 printf("FileSndFile::read_samples buffer=%p\n", buffer);
699 //printf("FileSndFile::read_samples 1 current_sample=%d len=%d\n", file->current_sample, len);
700 if(temp_allocated && temp_allocated < len)
702 //printf("FileSndFile::read_samples 1\n");
703 delete [] temp_double;
710 temp_allocated = len;
711 //printf("FileSndFile::read_samples 2\n");
712 temp_double = new double[len * asset->channels];
715 //printf("FileSndFile::read_samples 3\n");
716 result = !sf_read_double(fd, temp_double, len * asset->channels);
717 //printf("FileSndFile::read_samples 4\n");
720 printf("FileSndFile::read_samples fd=%p temp_double=%p len=%d asset=%p asset->channels=%d\n",
721 fd, temp_double, len, asset, asset->channels);
723 //printf("FileSndFile::read_samples 4\n");
724 // Extract single channel
725 for(int i = 0, j = file->current_channel;
727 i++, j += asset->channels)
729 buffer[i] = temp_double[j];
731 //printf("FileSndFile::read_samples 6\n");
736 int FileSndFile::write_samples(double **buffer, int64_t len)
740 // Get temp buffer for interleaved channels
741 //printf("FileSndFile::read_samples 1\n");
742 if(temp_allocated && temp_allocated < len)
745 delete [] temp_double;
749 //printf("FileSndFile::read_samples 2\n");
752 temp_allocated = len;
753 temp_double = new double[len * asset->channels];
756 // Interleave channels
757 for(int i = 0; i < asset->channels; i++)
759 for(int j = 0; j < len; j++)
761 double sample = buffer[i][j];
762 // Libsndfile does not limit values
763 //if(sample > 1.0 || sample < -1.0) printf("FileSndFile::write_samples %f\n", sample);
764 CLAMP(sample, -1.0, (32767.0 / 32768.0));
765 temp_double[j * asset->channels + i] = sample;
769 result = !sf_writef_double(fd, temp_double, len);
774 void FileSndFile::get_parameters(BC_WindowBase *parent_window,
776 BC_WindowBase* &format_window,
782 SndFileConfig *window = new SndFileConfig(parent_window, asset);
783 format_window = window;
784 window->create_objects();
785 window->run_window();
790 SndFileConfig::SndFileConfig(BC_WindowBase *parent_window, Asset *asset)
791 : BC_Window(PROGRAM_NAME ": Audio Compression",
792 parent_window->get_abs_cursor_x(),
793 parent_window->get_abs_cursor_y(),
797 this->parent_window = parent_window;
801 SndFileConfig::~SndFileConfig()
803 if(bits_popup) delete bits_popup;
805 int SndFileConfig::create_objects()
810 switch(asset->format)
815 add_tool(new BC_Title(x, y, _("Compression:")));
817 if(asset->format == FILE_WAV)
818 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 1, 1, 0);
820 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
822 bits_popup->create_objects();
827 if(asset->format != FILE_AU)
828 add_subwindow(new BC_CheckBox(x, y, &asset->dither, _("Dither")));
830 if(asset->format == FILE_PCM)
832 add_subwindow(new BC_CheckBox(x, y, &asset->signed_, _("Signed")));
834 add_subwindow(new BC_Title(x, y, _("Byte order:")));
835 add_subwindow(hilo = new SndFileHILO(this, x + 100, y));
836 add_subwindow(lohi = new SndFileLOHI(this, x + 170, y));
838 add_subwindow(new BC_OKButton(this));
842 int SndFileConfig::close_event()
850 SndFileHILO::SndFileHILO(SndFileConfig *gui, int x, int y)
851 : BC_Radial(x, y, gui->asset->byte_order == 0, _("Hi Lo"))
855 int SndFileHILO::handle_event()
857 gui->asset->byte_order = 0;
858 gui->lohi->update(0);
865 SndFileLOHI::SndFileLOHI(SndFileConfig *gui, int x, int y)
866 : BC_Radial(x, y, gui->asset->byte_order == 1, _("Lo Hi"))
870 int SndFileLOHI::handle_event()
872 gui->asset->byte_order = 1;
873 gui->hilo->update(0);
876 #endif // #ifdef HAVE_LIBSNDFILE_0