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