/********************************************************************** Audacity: A Digital Audio Editor FileFormats.cpp Dominic Mazzoni *******************************************************************//*! \file FileFormats.cpp \brief Works with libsndfile to provide encoding and other file information. *//*******************************************************************/ #include "Audacity.h" #include "FileFormats.h" #include <wx/arrstr.h> #include <wx/intl.h> #include "sndfile.h" #include "Internat.h" #include "widgets/AudacityMessageBox.h" #ifndef SNDFILE_1 #error Requires libsndfile 1.0 or higher #endif // // enumerating headers // int sf_num_headers() { int count; sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count)); return count; } wxString sf_header_index_name(int format) { SF_FORMAT_INFO format_info; memset(&format_info, 0, sizeof(format_info)); format_info.format = format; sf_command(NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ; return LAT1CTOWX(format_info.name); } unsigned int sf_header_index_to_type(int i) { SF_FORMAT_INFO format_info ; memset(&format_info, 0, sizeof(format_info)); format_info.format = i; sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)); return format_info.format & SF_FORMAT_TYPEMASK; } // // enumerating encodings // int sf_num_encodings() { int count ; sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ; return count; } wxString sf_encoding_index_name(int i) { SF_FORMAT_INFO format_info ; memset(&format_info, 0, sizeof(format_info)); format_info.format = i; sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)); return sf_normalize_name(format_info.name); } unsigned int sf_encoding_index_to_subtype(int i) { SF_FORMAT_INFO format_info ; memset(&format_info, 0, sizeof(format_info)); format_info.format = i; sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)); return format_info.format & SF_FORMAT_SUBMASK; } // // getting info about an actual SF format // wxString sf_header_name(int format) { SF_FORMAT_INFO format_info; memset(&format_info, 0, sizeof(format_info)); format_info.format = (format & SF_FORMAT_TYPEMASK); sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info)); return LAT1CTOWX(format_info.name); } wxString sf_header_shortname(int format) { SF_FORMAT_INFO format_info; int i; wxString s; memset(&format_info, 0, sizeof(format_info)); format_info.format = (format & SF_FORMAT_TYPEMASK); sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info)); MallocString<> tmp { strdup( format_info.name ) }; i = 0; while(tmp[i]) { if (tmp[i]==' ') tmp[i] = 0; else i++; } s = LAT1CTOWX(tmp.get()); return s; } wxString sf_header_extension(int format) { SF_FORMAT_INFO format_info; memset(&format_info, 0, sizeof(format_info)); format_info.format = (format & SF_FORMAT_TYPEMASK); sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info)); return LAT1CTOWX(format_info.extension); } wxString sf_encoding_name(int encoding) { SF_FORMAT_INFO format_info; memset(&format_info, 0, sizeof(format_info)); format_info.format = (encoding & SF_FORMAT_SUBMASK); sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info)); return sf_normalize_name(format_info.name); } int sf_num_simple_formats() { int count ; sf_command (NULL, SFC_GET_SIMPLE_FORMAT_COUNT, &count, sizeof (int)) ; return count; } static SF_FORMAT_INFO g_format_info; SF_FORMAT_INFO *sf_simple_format(int i) { memset(&g_format_info, 0, sizeof(g_format_info)); g_format_info.format = i; sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &g_format_info, sizeof(g_format_info)); return &g_format_info; } bool sf_subtype_more_than_16_bits(unsigned int format) { unsigned int subtype = format & SF_FORMAT_SUBMASK; return (subtype == SF_FORMAT_FLOAT || subtype == SF_FORMAT_DOUBLE || subtype == SF_FORMAT_PCM_24 || subtype == SF_FORMAT_PCM_32); } bool sf_subtype_is_integer(unsigned int format) { unsigned int subtype = format & SF_FORMAT_SUBMASK; return (subtype == SF_FORMAT_PCM_16 || subtype == SF_FORMAT_PCM_24 || subtype == SF_FORMAT_PCM_32); } FileExtensions sf_get_all_extensions() { FileExtensions exts; SF_FORMAT_INFO format_info; int count, k; memset(&format_info, 0, sizeof(format_info)); sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count)); for(k=0; k<count; k++) { format_info.format = k; sf_command(NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ; exts.push_back(LAT1CTOWX(format_info.extension)); } // Some other extensions that are often sound files // but aren't included by libsndfile exts.insert( exts.end(), { wxT("aif") , // AIFF file with a DOS-style extension wxT("ircam") , wxT("snd") , wxT("svx") , wxT("svx8") , wxT("sv16") , } ); return exts; } wxString sf_normalize_name(const char *name) { wxString n = LAT1CTOWX(name); n.Replace(wxT("8 bit"), wxT("8-bit")); n.Replace(wxT("16 bit"), wxT("16-bit")); n.Replace(wxT("24 bit"), wxT("24-bit")); n.Replace(wxT("32 bit"), wxT("32-bit")); n.Replace(wxT("64 bit"), wxT("64-bit")); return n; } #ifdef __WXMAC__ // TODO: find out the appropriate OSType // for the ones with an '????'. The others // are at least the same type used by // SoundApp. #define NUM_HEADERS 13 // // Mac OS 4-char type // # ifdef __UNIX__ # include <CoreServices/CoreServices.h> # else # include <Types.h> # endif OSType MacNames[NUM_HEADERS] = { 'WAVE', // WAVE 'AIFF', // AIFF 'NeXT', // Sun/NeXT AU 'BINA', // RAW i.e. binary 'PAR ', // ??? Ensoniq PARIS '8SVX', // Amiga IFF / SVX8 'NIST', // ??? NIST/Sphere 'VOC ', // VOC '\?\?\?\?', // ?? Propellorheads Rex 'SF ', // ?? IRCAM 'W64 ', // ?? Wave64 'MAT4', // ?? Matlab 4 'MAT5', // ?? Matlab 5 }; static OSType sf_header_mactype(int format) { if (format >= 0x10000) return MacNames[(format/0x10000)-1]; else if (format>=0 && format<NUM_HEADERS) return MacNames[format]; else return '\?\?\?\?'; } #endif // __WXMAC__ ODLock libSndFileMutex; int SFFileCloser::operator() (SNDFILE *sf) const { auto err = SFCall<int>(sf_close, sf); if (err) { char buffer[1000]; sf_error_str(sf, buffer, 1000); AudacityMessageBox(wxString::Format /* i18n-hint: %s will be the error message from libsndfile */ (_("Error (file may not have been written): %s"), buffer)); } return err; }