00001 #include "asset.h"
00002 #include "assets.h"
00003 #include "bcsignals.h"
00004 #include "bitspopup.h"
00005 #include "clip.h"
00006 #include "file.h"
00007 #include "filesndfile.h"
00008 #include "language.h"
00009 #include "mwindow.inc"
00010
00011
00012 FileSndFile::FileSndFile(Asset *asset, File *file)
00013 : FileBase(asset, file)
00014 {
00015 temp_double = 0;
00016 temp_allocated = 0;
00017 fd_config.format = 0;
00018 fd = 0;
00019 }
00020
00021 FileSndFile::~FileSndFile()
00022 {
00023 if(temp_double) delete [] temp_double;
00024 }
00025
00026 int FileSndFile::check_sig(Asset *asset)
00027 {
00028 int result = 0;
00029 SF_INFO fd_config;
00030 fd_config.format = 0;
00031 SNDFILE *fd = sf_open(asset->path, SFM_READ, &fd_config);
00032 if(fd)
00033 {
00034 sf_close(fd);
00035 result = 1;
00036 }
00037
00038 return result;
00039 }
00040
00041 void FileSndFile::asset_to_format()
00042 {
00043 switch(asset->format)
00044 {
00045 case FILE_PCM: fd_config.format = SF_FORMAT_RAW; break;
00046 case FILE_WAV: fd_config.format = SF_FORMAT_WAV; break;
00047 case FILE_AU: fd_config.format = SF_FORMAT_AU; break;
00048 case FILE_AIFF: fd_config.format = SF_FORMAT_AIFF; break;
00049 }
00050
00051
00052
00053 switch(asset->bits)
00054 {
00055 case BITSLINEAR8:
00056 if(asset->signed_)
00057 fd_config.format |= SF_FORMAT_PCM_S8;
00058 else
00059 fd_config.format |= SF_FORMAT_PCM_U8;
00060 break;
00061
00062 case BITSLINEAR16:
00063 fd_config.format |= SF_FORMAT_PCM_16;
00064
00065 if(asset->byte_order || asset->format == FILE_WAV)
00066 fd_config.format |= SF_ENDIAN_LITTLE;
00067 else
00068 fd_config.format |= SF_ENDIAN_BIG;
00069 break;
00070
00071 case BITSLINEAR24:
00072 fd_config.format |= SF_FORMAT_PCM_24;
00073
00074 if(asset->byte_order || asset->format == FILE_WAV)
00075 fd_config.format |= SF_ENDIAN_LITTLE;
00076 else
00077 fd_config.format |= SF_ENDIAN_BIG;
00078 break;
00079
00080 case BITSLINEAR32:
00081 fd_config.format |= SF_FORMAT_PCM_32;
00082
00083 if(asset->byte_order || asset->format == FILE_WAV)
00084 fd_config.format |= SF_ENDIAN_LITTLE;
00085 else
00086 fd_config.format |= SF_ENDIAN_BIG;
00087 break;
00088
00089 case BITSULAW:
00090 fd_config.format |= SF_FORMAT_ULAW;
00091 break;
00092
00093 case BITSFLOAT:
00094 fd_config.format |= SF_FORMAT_FLOAT;
00095 break;
00096
00097 case BITS_ADPCM:
00098 if(fd_config.format == FILE_WAV)
00099 fd_config.format |= SF_FORMAT_MS_ADPCM;
00100 else
00101 fd_config.format |= SF_FORMAT_IMA_ADPCM;
00102 fd_config.format |= SF_FORMAT_PCM_16;
00103 break;
00104 }
00105
00106 fd_config.seekable = 1;
00107 fd_config.samplerate = asset->sample_rate;
00108 fd_config.channels = asset->channels;
00109
00110 }
00111
00112 void FileSndFile::format_to_asset()
00113 {
00114
00115
00116 if(asset->format == 0)
00117 {
00118 asset->byte_order = 0;
00119 asset->signed_ = 1;
00120 switch(fd_config.format & SF_FORMAT_TYPEMASK)
00121 {
00122 case SF_FORMAT_WAV:
00123 asset->format = FILE_WAV;
00124 asset->byte_order = 1;
00125 asset->header = 44;
00126 break;
00127 case SF_FORMAT_AIFF: asset->format = FILE_AIFF; break;
00128 case SF_FORMAT_AU: asset->format = FILE_AU; break;
00129 case SF_FORMAT_RAW: asset->format = FILE_PCM; break;
00130 case SF_FORMAT_PAF: asset->format = FILE_SND; break;
00131 case SF_FORMAT_SVX: asset->format = FILE_SND; break;
00132 case SF_FORMAT_NIST: asset->format = FILE_SND; break;
00133 }
00134
00135 switch(fd_config.format & SF_FORMAT_SUBMASK)
00136 {
00137 case SF_FORMAT_FLOAT:
00138 asset->bits = BITSFLOAT;
00139 break;
00140 case SF_FORMAT_ULAW:
00141 asset->bits = BITSULAW;
00142 break;
00143 case SF_FORMAT_IMA_ADPCM:
00144 case SF_FORMAT_MS_ADPCM:
00145 asset->bits = BITS_ADPCM;
00146 break;
00147 case SF_FORMAT_PCM_16:
00148 asset->signed_ = 1;
00149 asset->bits = 16;
00150 break;
00151 case SF_FORMAT_PCM_24:
00152 asset->signed_ = 1;
00153 asset->bits = 24;
00154 break;
00155 case SF_FORMAT_PCM_32:
00156 asset->signed_ = 1;
00157 asset->bits = 32;
00158 break;
00159 case SF_FORMAT_PCM_S8:
00160 asset->signed_ = 1;
00161 asset->bits = BITSLINEAR8;
00162 break;
00163 case SF_FORMAT_PCM_U8:
00164 asset->signed_ = 0;
00165 asset->bits = BITSLINEAR8;
00166 break;
00167 }
00168
00169 switch(fd_config.format & SF_FORMAT_ENDMASK)
00170 {
00171 case SF_ENDIAN_LITTLE:
00172 asset->byte_order = 1;
00173 break;
00174 case SF_ENDIAN_BIG:
00175 asset->byte_order = 0;
00176 break;
00177 }
00178
00179 asset->channels = fd_config.channels;
00180 }
00181
00182 asset->audio_data = 1;
00183 asset->audio_length = fd_config.frames;
00184 if(!asset->sample_rate)
00185 asset->sample_rate = fd_config.samplerate;
00186
00187
00188 }
00189
00190 int FileSndFile::open_file(int rd, int wr)
00191 {
00192 int result = 0;
00193 this->rd = rd;
00194 this->wr = wr;
00195
00196 if(rd)
00197 {
00198 if(asset->format == FILE_PCM)
00199 {
00200 asset_to_format();
00201 fd = sf_open(asset->path, SFM_READ, &fd_config);
00202
00203 if(fd) format_to_asset();
00204 }
00205 else
00206 {
00207 fd = sf_open(asset->path, SFM_READ, &fd_config);
00208
00209 if(fd) format_to_asset();
00210 }
00211 SET_TRACE
00212 }
00213 else
00214 if(wr)
00215 {
00216 asset_to_format();
00217 fd = sf_open(asset->path, SFM_WRITE, &fd_config);
00218 }
00219
00220 if(!fd)
00221 {
00222 result = 1;
00223 printf("FileSndFile::open_file: ");
00224 sf_perror(0);
00225 }
00226
00227 return result;
00228 }
00229
00230 int FileSndFile::close_file()
00231 {
00232 if(fd) sf_close(fd);
00233 fd = 0;
00234 FileBase::close_file();
00235 fd_config.format = 0;
00236 return 0;
00237 }
00238
00239 int FileSndFile::set_audio_position(int64_t sample)
00240 {
00241
00242 if(sf_seek(fd, sample, SEEK_SET) < 0)
00243 {
00244 printf("FileSndFile::set_audio_position %lld: failed\n", sample);
00245 sf_perror(fd);
00246 return 1;
00247 }
00248 return 0;
00249 }
00250
00251 int FileSndFile::read_samples(double *buffer, int64_t len)
00252 {
00253 int result = 0;
00254
00255
00256
00257 if(len <= 0 || len > 1000000)
00258 printf("FileSndFile::read_samples len=%d\n", len);
00259
00260 if(!buffer)
00261 printf("FileSndFile::read_samples buffer=%p\n", buffer);
00262
00263 if(temp_allocated && temp_allocated < len)
00264 {
00265 delete [] temp_double;
00266 temp_double = 0;
00267 temp_allocated = 0;
00268 }
00269
00270 if(!temp_allocated)
00271 {
00272 temp_allocated = len;
00273 temp_double = new double[len * asset->channels];
00274 }
00275
00276 result = !sf_read_double(fd, temp_double, len * asset->channels);
00277
00278 if(result)
00279 printf("FileSndFile::read_samples fd=%p temp_double=%p len=%d asset=%p asset->channels=%d\n",
00280 fd, temp_double, len, asset, asset->channels);
00281
00282
00283 for(int i = 0, j = file->current_channel;
00284 i < len;
00285 i++, j += asset->channels)
00286 {
00287 buffer[i] = temp_double[j];
00288 }
00289
00290 return result;
00291 }
00292
00293 int FileSndFile::write_samples(double **buffer, int64_t len)
00294 {
00295 int result = 0;
00296
00297
00298
00299 if(temp_allocated && temp_allocated < len)
00300 {
00301 temp_allocated = 0;
00302 delete [] temp_double;
00303 temp_double = 0;
00304 }
00305
00306
00307 if(!temp_allocated)
00308 {
00309 temp_allocated = len;
00310 temp_double = new double[len * asset->channels];
00311 }
00312
00313
00314 for(int i = 0; i < asset->channels; i++)
00315 {
00316 for(int j = 0; j < len; j++)
00317 {
00318 double sample = buffer[i][j];
00319
00320
00321
00322 if(asset->bits != BITSFLOAT) CLAMP(sample, -1.0, (32767.0 / 32768.0));
00323 temp_double[j * asset->channels + i] = sample;
00324 }
00325 }
00326
00327 result = !sf_writef_double(fd, temp_double, len);
00328
00329 return result;
00330 }
00331
00332 void FileSndFile::get_parameters(BC_WindowBase *parent_window,
00333 Asset *asset,
00334 BC_WindowBase* &format_window,
00335 int audio_options,
00336 int video_options)
00337 {
00338 if(audio_options)
00339 {
00340 SndFileConfig *window = new SndFileConfig(parent_window, asset);
00341 format_window = window;
00342 window->create_objects();
00343 window->run_window();
00344 delete window;
00345 }
00346 }
00347
00348 SndFileConfig::SndFileConfig(BC_WindowBase *parent_window, Asset *asset)
00349 : BC_Window(PROGRAM_NAME ": Audio Compression",
00350 parent_window->get_abs_cursor_x(1),
00351 parent_window->get_abs_cursor_y(1),
00352 250,
00353 250)
00354 {
00355 this->parent_window = parent_window;
00356 this->asset = asset;
00357 }
00358
00359 SndFileConfig::~SndFileConfig()
00360 {
00361 if(bits_popup) delete bits_popup;
00362 }
00363 int SndFileConfig::create_objects()
00364 {
00365 int x = 10, y = 10;
00366
00367 bits_popup = 0;
00368 switch(asset->format)
00369 {
00370 case FILE_WAV:
00371 case FILE_PCM:
00372 case FILE_AIFF:
00373 add_tool(new BC_Title(x, y, _("Compression:")));
00374 y += 25;
00375 if(asset->format == FILE_WAV)
00376 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 1, 1, 0);
00377 else
00378 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
00379 y += 40;
00380 bits_popup->create_objects();
00381 break;
00382 }
00383
00384 x = 10;
00385 if(asset->format != FILE_AU)
00386 add_subwindow(new BC_CheckBox(x, y, &asset->dither, _("Dither")));
00387 y += 30;
00388 if(asset->format == FILE_PCM)
00389 {
00390 add_subwindow(new BC_CheckBox(x, y, &asset->signed_, _("Signed")));
00391 y += 35;
00392 add_subwindow(new BC_Title(x, y, _("Byte order:")));
00393 add_subwindow(hilo = new SndFileHILO(this, x + 100, y));
00394 add_subwindow(lohi = new SndFileLOHI(this, x + 170, y));
00395 }
00396 add_subwindow(new BC_OKButton(this));
00397 return 0;
00398 }
00399
00400 int SndFileConfig::close_event()
00401 {
00402 set_done(0);
00403 return 1;
00404 }
00405
00406
00407
00408 SndFileHILO::SndFileHILO(SndFileConfig *gui, int x, int y)
00409 : BC_Radial(x, y, gui->asset->byte_order == 0, _("Hi Lo"))
00410 {
00411 this->gui = gui;
00412 }
00413 int SndFileHILO::handle_event()
00414 {
00415 gui->asset->byte_order = 0;
00416 gui->lohi->update(0);
00417 return 1;
00418 }
00419
00420
00421
00422
00423 SndFileLOHI::SndFileLOHI(SndFileConfig *gui, int x, int y)
00424 : BC_Radial(x, y, gui->asset->byte_order == 1, _("Lo Hi"))
00425 {
00426 this->gui = gui;
00427 }
00428 int SndFileLOHI::handle_event()
00429 {
00430 gui->asset->byte_order = 1;
00431 gui->hilo->update(0);
00432 return 1;
00433 }
00434
00435