From a32f8ca17a633eeab8b009ba1f6589d61decaf01 Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Sat, 26 Apr 2008 00:33:04 -0500 Subject: [PATCH] Allow the user to choose capture format. --- Timeline/Audio_File.C | 12 ++++++++ Timeline/Audio_File.H | 21 ++++++++++++- Timeline/Audio_File_SF.C | 32 +++++++++++++++++--- Timeline/Audio_File_SF.H | 2 ++ Timeline/TLE.fl | 65 +++++++++++++++++++++++++++++++++------- Timeline/Track.C | 6 ++-- Timeline/Track.H | 2 ++ 7 files changed, 122 insertions(+), 18 deletions(-) diff --git a/Timeline/Audio_File.C b/Timeline/Audio_File.C index ba2a5d2..7eee64c 100644 --- a/Timeline/Audio_File.C +++ b/Timeline/Audio_File.C @@ -27,6 +27,18 @@ Audio_File::~Audio_File ( ) _open_files[ std::string( _filename ) ] = NULL; } +void +Audio_File::all_supported_formats ( std::list &formats ) +{ + const format_desc *fd; + + fd = Audio_File_SF::supported_formats; + + for ( ; fd->name; ++fd ) + formats.push_back( fd->name ); +} + + /** attmpet to open any supported filetype */ Audio_File * Audio_File::from_file ( const char * filename ) diff --git a/Timeline/Audio_File.H b/Timeline/Audio_File.H index 4a66b6e..1fbc316 100644 --- a/Timeline/Audio_File.H +++ b/Timeline/Audio_File.H @@ -25,9 +25,9 @@ #include "types.h" #include "Peaks.H" - #include #include +#include class Peak_Writer; @@ -37,6 +37,12 @@ class Audio_File protected: + struct format_desc + { + const char *name; + const char *extension; + unsigned long id; + }; const char *_filename; nframes_t _length; /* length of file in samples */ @@ -47,6 +53,17 @@ protected: Peak_Writer *_peak_writer; + static const format_desc * + find_format ( const format_desc *fd, const char *name ) + { + for ( ; fd->name; ++fd ) + if ( ! strcmp( fd->name, name ) ) + return fd; + + return NULL; + } + + public: Audio_File ( ) @@ -57,6 +74,8 @@ public: virtual ~Audio_File ( ); + static void all_supported_formats ( std::list &formats ); + static Audio_File *from_file ( const char *filename ); Peaks const * peaks ( ) { return _peaks; } diff --git a/Timeline/Audio_File_SF.C b/Timeline/Audio_File_SF.C index 05c3f9b..5e0c7e1 100644 --- a/Timeline/Audio_File_SF.C +++ b/Timeline/Audio_File_SF.C @@ -29,6 +29,22 @@ #include "Peaks.H" +// #define HAS_SF_FORMAT_VORBIS + +const Audio_File::format_desc Audio_File_SF::supported_formats[] = +{ + { "Wav 24", "wav", SF_FORMAT_WAV | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, + { "Wav 16", "wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, + { "Wav f32", "wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT | SF_ENDIAN_FILE }, + { "Au 24", "au", SF_FORMAT_AU | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, + { "Au 16", "au", SF_FORMAT_AU | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, + { "FLAC", "flac", SF_FORMAT_FLAC | SF_FORMAT_PCM_24 }, +#ifdef HAS_SF_FORMAT_VORBIS + { "Ogg Vorbis", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS | SF_FORMAT_PCM_16 }, +#endif + { 0, 0 } +}; + Audio_File_SF * Audio_File_SF::from_file ( const char *filename ) { @@ -78,21 +94,29 @@ Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels memset( &si, 0, sizeof( si ) ); + const Audio_File::format_desc *fd = Audio_File::find_format( Audio_File_SF::supported_formats, format ); + + if ( ! fd ) + return (Audio_File_SF *)1; + si.samplerate = samplerate; si.channels = channels; + si.format = fd->id; - /* FIXME: bogus */ - si.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24 | SF_ENDIAN_CPU; + char *name; + asprintf( &name, "%s.%s", filename, fd->extension ); - if ( ! ( out = sf_open( filename, SFM_RDWR, &si ) ) ) +// if ( ! ( out = sf_open( name, SFM_RDWR, &si ) ) ) + if ( ! ( out = sf_open( name, SFM_WRITE, &si ) ) ) { printf( "couldn't create soundfile.\n" ); + free( name ); return NULL; } Audio_File_SF *c = new Audio_File_SF; - c->_filename = strdup( filename ); + c->_filename = name; c->_length = 0; c->_samplerate = samplerate; c->_channels = channels; diff --git a/Timeline/Audio_File_SF.H b/Timeline/Audio_File_SF.H index 2d5413d..a97a44c 100644 --- a/Timeline/Audio_File_SF.H +++ b/Timeline/Audio_File_SF.H @@ -33,6 +33,8 @@ class Audio_File_SF : public Audio_File public: + static const Audio_File::format_desc supported_formats[]; + static Audio_File_SF *from_file ( const char *filename ); static Audio_File_SF *create ( const char *filename, nframes_t samplerate, int channels, const char *format ); diff --git a/Timeline/TLE.fl b/Timeline/TLE.fl index 0812be0..2105793 100644 --- a/Timeline/TLE.fl +++ b/Timeline/TLE.fl @@ -17,6 +17,11 @@ decl {\#include "Loggable.H"} {} decl {\#include "Clock.H"} {public } +decl {\#include "Track.H" // for capture_format} {selected +} + +decl {\#include "Audio_File.H" // for supported formats} {} + decl {\#include "Waveform.H" // for options} {} decl {\#include "Control_Sequence.H" // for options} {} @@ -36,6 +41,32 @@ class TLE {open } { code {return m->menu()[ m->value() ].flags & FL_MENU_VALUE;} {} } + Function {save()} {open + } { + code {const char options_filename[] = "options"; +const char state_filename[] = "state"; + +// save options + +char *path; +asprintf( &path, "%s/%s", user_config_dir, options_filename ); +((Fl_Menu_Settings*)menubar)->dump( options_menu, path ); +free( path ); + +// save unjournaled state + +// Loggable::save_unjournaled( state_filename );} {} + } + Function {capture_format_cb( Fl_Widget *w, void *v )} {open private return_type {static void} + } { + code {((TLE*)v)->capture_format_cb();} {} + } + Function {capture_format_cb()} {open private return_type void + } { + code {Fl_Menu_ *o = menubar; + +Track::capture_format = o->menu()[ o->value() ].label();} {} + } Function {TLE()} {open } { code {make_window(); @@ -52,7 +83,22 @@ Fl::add_timeout( STATUS_UPDATE_FREQ, update_cb, this ); char *path; asprintf( &path, "%s/options", user_config_dir ); ((Fl_Menu_Settings*)menubar)->load( options_menu, path ); -free( path );} {} +free( path ); + + +std::list formats; + +Audio_File::all_supported_formats( formats ); + +for ( std::list ::const_iterator f = formats.begin(); f != formats.end(); ++f ) +{ +// capture_format_menu->add( *f, FL_MENU_RADIO, 0, 0, 0 ); +//; + char pat[256]; + snprintf( pat, sizeof( pat ), "Timeline/Capture Format/%s", *f ); + + menubar->add( pat, 0, &TLE::capture_format_cb, this, FL_MENU_RADIO ); +}} {} } Function {make_window()} {open } { @@ -60,8 +106,7 @@ free( path );} {} label {Non-DAW - Timeline} open xywh {522 141 1024 768} type Double resizable xclass {Non-DAW} visible } { - Fl_Menu_Bar menubar { - label {capture:\\nfoo} open + Fl_Menu_Bar menubar {open xywh {0 0 1024 25} } { Submenu {} { @@ -101,10 +146,7 @@ Loggable::compact();} } MenuItem {} { label {&Quit} - callback {char *path; -asprintf( &path, "%s/options", user_config_dir ); -((Fl_Menu_Settings*)menubar)->dump( options_menu, path ); -free( path ); + callback {save(); exit( 0 );} xywh {40 40 40 25} shortcut 0x40071 @@ -120,7 +162,7 @@ exit( 0 );} } MenuItem {} { label Undo - callback {Loggable::undo();} selected + callback {Loggable::undo();} xywh {0 0 40 25} shortcut 0x4007a } } @@ -213,6 +255,10 @@ exit( 0 );} xywh {20 20 40 25} type Radio } } + Submenu {} { + label {Capture Format} open + xywh {0 0 74 25} + } {} } Submenu options_menu { label {&Options} @@ -446,6 +492,3 @@ update_progress( cpu_load_progress, clp, engine->cpu_load() );} {} ((TLE*)v)->update_status();} {} } } - -Function {make_window()} {open -} {} diff --git a/Timeline/Track.C b/Timeline/Track.C index 71f2ae0..fd93c9d 100644 --- a/Timeline/Track.C +++ b/Timeline/Track.C @@ -32,6 +32,8 @@ int Track::_soloing = 0; +const char *Track::capture_format = "Wav 24"; + void Track::cb_input_field ( Fl_Widget *w, void *v ) { @@ -639,10 +641,10 @@ Track::record ( nframes_t frame ) char pat[256]; - snprintf( pat, sizeof( pat ), "%s-%llu.wav", name(), uuid() ); + snprintf( pat, sizeof( pat ), "%s-%llu", name(), uuid() ); /* FIXME: hack */ - Audio_File *af = Audio_File_SF::create( pat, 48000, input.size(), "Wav/24" ); + Audio_File *af = Audio_File_SF::create( pat, 48000, input.size(), Track::capture_format ); _capture = new Region( af, track(), frame ); diff --git a/Timeline/Track.H b/Timeline/Track.H index 1dfb55a..89a1e3d 100644 --- a/Timeline/Track.H +++ b/Timeline/Track.H @@ -56,6 +56,8 @@ public: static bool soloing ( void ) { return _soloing; } + static const char *capture_format; + private: static int _soloing;