Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

filesndfile.C

Go to the documentation of this file.
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 // Not all of these are allowed in all sound formats.
00052 // Raw can't be float.
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 //printf("FileSndFile::asset_to_format %x %d %d\n", fd_config.format, fd_config.pcmbitwidth, fd_config.channels);
00110 }
00111 
00112 void FileSndFile::format_to_asset()
00113 {
00114 //printf("FileSndFile::format_to_asset 1\n");
00115 // User supplies values if PCM
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 //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);
00187 //asset->dump();
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 // Already given by user
00203                         if(fd) format_to_asset();
00204                 }
00205                 else
00206                 {
00207                         fd = sf_open(asset->path, SFM_READ, &fd_config);
00208 // Doesn't calculate the length
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 // Commented out /* && psf->dataoffset */ in sndfile.c: 761
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 //printf("FileSndFile::read_samples %lld %lld\n", file->current_sample, len);
00256 // Get temp buffer for interleaved channels
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 // Extract single channel
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 // Get temp buffer for interleaved channels
00298 //printf("FileSndFile::read_samples 1\n");
00299         if(temp_allocated && temp_allocated < len)
00300         {
00301                 temp_allocated = 0;
00302                 delete [] temp_double;
00303                 temp_double = 0;
00304         }
00305 
00306 //printf("FileSndFile::read_samples 2\n");
00307         if(!temp_allocated)
00308         {
00309                 temp_allocated = len;
00310                 temp_double = new double[len * asset->channels];
00311         }
00312 
00313 // Interleave channels
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 // Libsndfile does not limit values
00320 //if(sample > 1.0 || sample < -1.0) printf("FileSndFile::write_samples %f\n", sample);
00321 //printf("FileSndFile::write_samples %d %d\n", asset->bits, BITSFLOAT);
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 

Generated on Sun Jan 8 13:38:55 2006 for Cinelerra-svn by  doxygen 1.4.4