4 #include "bcwidgetgrid.h"
8 #include "filesndfile.h"
10 #include "mwindow.inc"
11 #include "mainerror.h"
13 FileSndFile::FileSndFile(Asset_GC asset, File *file)
14 : FileBase(asset, file)
22 FileSndFile::~FileSndFile()
24 if(temp_double) delete [] temp_double;
27 int FileSndFile::check_sig(Asset_GC asset)
32 SNDFILE *fd = sf_open(asset->path, SFM_READ, &fd_config);
42 void FileSndFile::asset_to_format()
46 case FILE_PCM: fd_config.format = SF_FORMAT_RAW; break;
47 case FILE_WAV: fd_config.format = SF_FORMAT_WAV; break;
48 case FILE_AU: fd_config.format = SF_FORMAT_AU; break;
49 case FILE_AIFF: fd_config.format = SF_FORMAT_AIFF; break;
52 // Not all of these are allowed in all sound formats.
53 // Raw can't be float.
57 if(asset->format == FILE_WAV)
58 fd_config.format |= SF_FORMAT_PCM_U8;
61 fd_config.format |= SF_FORMAT_PCM_S8;
63 fd_config.format |= SF_FORMAT_PCM_U8;
67 fd_config.format |= SF_FORMAT_PCM_16;
69 if(asset->byte_order || asset->format == FILE_WAV)
70 fd_config.format |= SF_ENDIAN_LITTLE;
72 fd_config.format |= SF_ENDIAN_BIG;
76 fd_config.format |= SF_FORMAT_PCM_24;
78 if(asset->byte_order || asset->format == FILE_WAV)
79 fd_config.format |= SF_ENDIAN_LITTLE;
81 fd_config.format |= SF_ENDIAN_BIG;
85 fd_config.format |= SF_FORMAT_PCM_32;
87 if(asset->byte_order || asset->format == FILE_WAV)
88 fd_config.format |= SF_ENDIAN_LITTLE;
90 fd_config.format |= SF_ENDIAN_BIG;
94 fd_config.format |= SF_FORMAT_ULAW;
98 fd_config.format |= SF_FORMAT_FLOAT;
102 if(fd_config.format == FILE_WAV)
103 fd_config.format |= SF_FORMAT_MS_ADPCM;
105 fd_config.format |= SF_FORMAT_IMA_ADPCM;
106 fd_config.format |= SF_FORMAT_PCM_16;
110 fd_config.seekable = 1;
111 fd_config.samplerate = asset->sample_rate;
112 fd_config.channels = asset->channels;
113 //printf("FileSndFile::asset_to_format %x %d %d\n", fd_config.format, fd_config.pcmbitwidth, fd_config.channels);
116 void FileSndFile::format_to_asset()
118 //printf("FileSndFile::format_to_asset 1\n");
119 // User supplies values if PCM
120 if(asset->format == 0)
122 asset->byte_order = 0;
124 switch(fd_config.format & SF_FORMAT_TYPEMASK)
127 asset->format = FILE_WAV;
128 asset->byte_order = 1;
131 case SF_FORMAT_AIFF: asset->format = FILE_AIFF; break;
132 case SF_FORMAT_AU: asset->format = FILE_AU; break;
133 case SF_FORMAT_RAW: asset->format = FILE_PCM; break;
134 case SF_FORMAT_PAF: asset->format = FILE_SND; break;
135 case SF_FORMAT_SVX: asset->format = FILE_SND; break;
136 case SF_FORMAT_NIST: asset->format = FILE_SND; break;
139 switch(fd_config.format & SF_FORMAT_SUBMASK)
141 case SF_FORMAT_FLOAT:
142 asset->bits = BITSFLOAT;
145 asset->bits = BITSULAW;
147 case SF_FORMAT_IMA_ADPCM:
148 case SF_FORMAT_MS_ADPCM:
149 asset->bits = BITS_ADPCM;
151 case SF_FORMAT_PCM_16:
155 case SF_FORMAT_PCM_24:
159 case SF_FORMAT_PCM_32:
163 case SF_FORMAT_PCM_S8:
165 asset->bits = BITSLINEAR8;
167 case SF_FORMAT_PCM_U8:
169 asset->bits = BITSLINEAR8;
173 switch(fd_config.format & SF_FORMAT_ENDMASK)
175 case SF_ENDIAN_LITTLE:
176 asset->byte_order = 1;
179 asset->byte_order = 0;
183 asset->channels = fd_config.channels;
186 asset->audio_data = 1;
187 asset->audio_length = fd_config.frames;
188 if(!asset->sample_rate)
189 asset->sample_rate = fd_config.samplerate;
190 //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);
194 int FileSndFile::open_file(int rd, int wr)
202 if(asset->format == FILE_PCM)
205 fd = sf_open(asset->path, SFM_READ, &fd_config);
206 // Already given by user
207 if(fd) format_to_asset();
211 fd = sf_open(asset->path, SFM_READ, &fd_config);
212 // Doesn't calculate the length
213 if(fd) format_to_asset();
220 printf("FileSNDFile::open 1\n");
222 printf("FileSNDFile::open 1\n");
223 fd = sf_open(asset->path, SFM_WRITE, &fd_config);
224 printf("FileSNDFile::open 10 %p\n", fd);
230 eprintf("%s", sf_strerror(0));
236 int FileSndFile::close_file()
240 FileBase::close_file();
241 fd_config.format = 0;
245 int FileSndFile::set_audio_position(int64_t sample)
247 // Commented out /* && psf->dataoffset */ in sndfile.c: 761
248 if(sf_seek(fd, sample, SEEK_SET) < 0)
250 eprintf("sf_seek() to sample %lld failed, reason: %s\n", sample, sf_strerror(fd));
256 int FileSndFile::read_samples(double *buffer, int64_t len)
260 //printf("FileSndFile::read_samples %lld %lld\n", file->current_sample, len);
261 // Get temp buffer for interleaved channels
262 if(len <= 0 || len > 1000000)
263 eprintf("len=%d\n", len);
266 eprintf("buffer=%p\n", buffer);
268 if(temp_allocated && temp_allocated < len)
270 delete [] temp_double;
277 temp_allocated = len;
278 temp_double = new double[len * asset->channels];
281 result = !sf_read_double(fd, temp_double, len * asset->channels);
284 eprintf("fd=%p temp_double=%p len=%d asset=%p asset->channels=%d\n",
285 fd, temp_double, len, asset, asset->channels);
287 // Extract single channel
288 for(int i = 0, j = file->current_channel;
290 i++, j += asset->channels)
292 buffer[i] = temp_double[j];
298 int FileSndFile::write_samples(double **buffer, int64_t len)
302 // Get temp buffer for interleaved channels
303 //printf("FileSndFile::read_samples 1\n");
304 if(temp_allocated && temp_allocated < len)
307 delete [] temp_double;
311 //printf("FileSndFile::read_samples 2\n");
314 temp_allocated = len;
315 temp_double = new double[len * asset->channels];
318 // Interleave channels
319 for(int i = 0; i < asset->channels; i++)
321 for(int j = 0; j < len; j++)
323 double sample = buffer[i][j];
324 // Libsndfile does not limit values
325 //if(sample > 1.0 || sample < -1.0) printf("FileSndFile::write_samples %f\n", sample);
326 //printf("FileSndFile::write_samples %d %d\n", asset->bits, BITSFLOAT);
327 if(asset->bits != BITSFLOAT) CLAMP(sample, -1.0, (32767.0 / 32768.0));
328 temp_double[j * asset->channels + i] = sample;
332 result = !sf_writef_double(fd, temp_double, len);
337 void FileSndFile::get_parameters(BC_WindowBase *parent_window,
339 BC_WindowBase* &format_window,
345 SndFileConfig *window = new SndFileConfig(parent_window, asset);
346 format_window = window;
347 window->create_objects();
348 window->run_window();
353 SndFileConfig::SndFileConfig(BC_WindowBase *parent_window, Asset_GC asset)
354 : BC_Window(PROGRAM_NAME ": Audio Compression",
355 parent_window->get_abs_cursor_x(1),
356 parent_window->get_abs_cursor_y(1),
364 this->parent_window = parent_window;
368 SndFileConfig::~SndFileConfig()
370 if(bits_popup) delete bits_popup;
372 int SndFileConfig::create_objects()
376 BC_WidgetGrid *wg, *wg2;
377 BC_RelocatableWidget *rw;
379 wg = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 3, 3));
382 switch(asset->format)
388 add_tool(new BC_Title(x, y, _("Compression:")));
390 if(asset->format == FILE_WAV)
391 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 1, 1, 0);
393 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
395 bits_popup->create_objects();
396 wg->add(rw, wg_row, 0);
397 wg->add(bits_popup, wg_row++, 1);
402 if(asset->format == FILE_AU)
405 add_subwindow(new BC_Title(x, y,_("There are no audio options for this format")));
406 wg->add(rw, wg_row++, 1);
410 if(asset->format != FILE_AU)
413 add_subwindow(new BC_CheckBox(x, y, &asset->dither, _("Dither")));
414 wg->add(rw, wg_row++, 1);
417 if(asset->format == FILE_PCM)
420 add_subwindow(new BC_CheckBox(x, y, &asset->signed_, _("Signed")));
421 wg->add(rw, wg_row++, 1);
424 add_subwindow(new BC_Title(x, y, _("Byte order:")));
425 add_subwindow(hilo = new SndFileHILO(this, x + 100, y));
426 add_subwindow(lohi = new SndFileLOHI(this, x + 170, y));
427 wg->add(rw, wg_row, 0);
428 wg2 = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 3, 3));
429 wg2->add(hilo, 0, 0);
430 wg2->add(lohi, 0, 1);
431 wg->add(wg2, wg_row++, 1);
434 add_subwindow(new BC_OKButton(this));
437 resize_window(wg->get_w_wm(), wg->get_h_wm() + rw->get_h());
441 int SndFileConfig::close_event()
449 SndFileHILO::SndFileHILO(SndFileConfig *gui, int x, int y)
450 : BC_Radial(x, y, gui->asset->byte_order == 0, _("Hi Lo"))
454 int SndFileHILO::handle_event()
456 gui->asset->byte_order = 0;
457 gui->lohi->update(0);
464 SndFileLOHI::SndFileLOHI(SndFileConfig *gui, int x, int y)
465 : BC_Radial(x, y, gui->asset->byte_order == 1, _("Lo Hi"))
469 int SndFileLOHI::handle_event()
471 gui->asset->byte_order = 1;
472 gui->hilo->update(0);
480 // c-file-style: "linux"