| @@ -74,15 +74,18 @@ DiskWriterPlugin::DiskWriterPlugin() : | |||||
| m_Recording(false) | m_Recording(false) | ||||
| { | { | ||||
| m_PluginInfo.Name="DiskWriter"; | m_PluginInfo.Name="DiskWriter"; | ||||
| m_PluginInfo.Width=100; | |||||
| m_PluginInfo.Height=66; | |||||
| m_PluginInfo.Width=140; | |||||
| m_PluginInfo.Height=90; | |||||
| m_PluginInfo.NumInputs=3; | m_PluginInfo.NumInputs=3; | ||||
| m_PluginInfo.NumOutputs=0; | m_PluginInfo.NumOutputs=0; | ||||
| m_PluginInfo.PortTips.push_back("Left Out"); | m_PluginInfo.PortTips.push_back("Left Out"); | ||||
| m_PluginInfo.PortTips.push_back("Right Out"); | m_PluginInfo.PortTips.push_back("Right Out"); | ||||
| m_PluginInfo.PortTips.push_back("Record Controller"); | m_PluginInfo.PortTips.push_back("Record Controller"); | ||||
| m_GUIArgs.BitsPerSample = 16; | |||||
| m_AudioCH->RegisterData("Filename",ChannelHandler::INPUT,m_GUIArgs.Name,256); | m_AudioCH->RegisterData("Filename",ChannelHandler::INPUT,m_GUIArgs.Name,256); | ||||
| m_AudioCH->Register("BitsPerSample",&m_GUIArgs.BitsPerSample,ChannelHandler::INPUT); | |||||
| } | } | ||||
| DiskWriterPlugin::~DiskWriterPlugin() | DiskWriterPlugin::~DiskWriterPlugin() | ||||
| @@ -107,12 +110,12 @@ SpiralGUIType *DiskWriterPlugin::CreateGUI() | |||||
| void DiskWriterPlugin::Execute() | void DiskWriterPlugin::Execute() | ||||
| { | { | ||||
| int Bps = m_GUIArgs.BitsPerSample/8; | |||||
| if(m_Recording && m_Wav.IsOpen()) | if(m_Recording && m_Wav.IsOpen()) | ||||
| { | { | ||||
| int on=0; | int on=0; | ||||
| float t; | float t; | ||||
| short Buffer[host->BUFSIZE*2]; | |||||
| short Buffer[host->BUFSIZE*Bps]; | |||||
| for (int n=0; n<host->BUFSIZE; n++) | for (int n=0; n<host->BUFSIZE; n++) | ||||
| { | { | ||||
| @@ -130,8 +133,8 @@ void DiskWriterPlugin::Execute() | |||||
| on++; | on++; | ||||
| } | } | ||||
| // stereo 16bit * bufsize | |||||
| m_Wav.Save(Buffer,host->BUFSIZE*2*2); | |||||
| // stereo Bps * bufsize | |||||
| m_Wav.Save(Buffer,host->BUFSIZE*2*Bps); | |||||
| } | } | ||||
| } | } | ||||
| @@ -145,6 +148,9 @@ void DiskWriterPlugin::ExecuteCommands() | |||||
| if (m_Wav.GetSamplerate() != GetHostInfo()->SAMPLERATE) { | if (m_Wav.GetSamplerate() != GetHostInfo()->SAMPLERATE) { | ||||
| m_Wav.SetSamplerate(GetHostInfo()->SAMPLERATE); | m_Wav.SetSamplerate(GetHostInfo()->SAMPLERATE); | ||||
| } | } | ||||
| if (m_Wav.GetBitsPerSample() != m_GUIArgs.BitsPerSample) { | |||||
| m_Wav.SetBitsPerSample(m_GUIArgs.BitsPerSample); | |||||
| } | |||||
| m_Wav.Open(m_GUIArgs.Name,WavFile::WRITE, WavFile::STEREO); | m_Wav.Open(m_GUIArgs.Name,WavFile::WRITE, WavFile::STEREO); | ||||
| break; | break; | ||||
| case CLOSEWAV : m_Wav.Close(); break; | case CLOSEWAV : m_Wav.Close(); break; | ||||
| @@ -40,6 +40,7 @@ public: | |||||
| struct GUIArgs | struct GUIArgs | ||||
| { | { | ||||
| char Name[256]; | char Name[256]; | ||||
| int BitsPerSample; | |||||
| }; | }; | ||||
| private: | private: | ||||
| @@ -25,7 +25,23 @@ using namespace std; | |||||
| DiskWriterPluginGUI::DiskWriterPluginGUI(int w, int h, SpiralPlugin *o, ChannelHandler *ch,const HostInfo *Info) : | DiskWriterPluginGUI::DiskWriterPluginGUI(int w, int h, SpiralPlugin *o, ChannelHandler *ch,const HostInfo *Info) : | ||||
| SpiralPluginGUI(w,h,o,ch) | SpiralPluginGUI(w,h,o,ch) | ||||
| { | { | ||||
| Open = new Fl_Button(5, 15, 90, 20, "Open"); | |||||
| m_16bits = new Fl_LED_Button (0, 15, 23, 23, "16bit"); | |||||
| m_16bits->type (FL_RADIO_BUTTON); | |||||
| m_16bits->labelsize(10); | |||||
| m_16bits->set(); | |||||
| m_16bits->callback((Fl_Callback*)cb_16bits); | |||||
| m_24bits = new Fl_LED_Button (0, 38, 23, 23, "24bit"); | |||||
| m_24bits->type (FL_RADIO_BUTTON); | |||||
| m_24bits->labelsize(10); | |||||
| m_24bits->callback((Fl_Callback*)cb_24bits); | |||||
| m_32bits = new Fl_LED_Button (0, 61, 23, 23, "32bit"); | |||||
| m_32bits->type (FL_RADIO_BUTTON); | |||||
| m_32bits->labelsize(10); | |||||
| m_32bits->callback((Fl_Callback*)cb_32bits); | |||||
| Open = new Fl_Button(50, 20, 90, 20, "Open"); | |||||
| Open->type(1); | Open->type(1); | ||||
| Open->box (FL_PLASTIC_UP_BOX); | Open->box (FL_PLASTIC_UP_BOX); | ||||
| Open->color (Info->GUI_COLOUR); | Open->color (Info->GUI_COLOUR); | ||||
| @@ -33,7 +49,7 @@ SpiralPluginGUI(w,h,o,ch) | |||||
| Open->labelsize(10); | Open->labelsize(10); | ||||
| Open->callback((Fl_Callback*)cb_Open); | Open->callback((Fl_Callback*)cb_Open); | ||||
| Record = new Fl_Button(5, 38, 90, 20, "Record"); | |||||
| Record = new Fl_Button(50, 60, 90, 20, "Record"); | |||||
| Record->type(1); | Record->type(1); | ||||
| Record->box (FL_PLASTIC_UP_BOX); | Record->box (FL_PLASTIC_UP_BOX); | ||||
| Record->color (Info->GUI_COLOUR); | Record->color (Info->GUI_COLOUR); | ||||
| @@ -74,6 +90,7 @@ inline void DiskWriterPluginGUI::cb_Open_i(Fl_Button* o, void* v) | |||||
| m_GUICH->SetCommand(DiskWriterPlugin::CLOSEWAV); | m_GUICH->SetCommand(DiskWriterPlugin::CLOSEWAV); | ||||
| } | } | ||||
| } | } | ||||
| void DiskWriterPluginGUI::cb_Open(Fl_Button* o, void* v) | void DiskWriterPluginGUI::cb_Open(Fl_Button* o, void* v) | ||||
| { ((DiskWriterPluginGUI*)(o->parent()))->cb_Open_i(o,v); } | { ((DiskWriterPluginGUI*)(o->parent()))->cb_Open_i(o,v); } | ||||
| @@ -85,6 +102,27 @@ inline void DiskWriterPluginGUI::cb_Record_i(Fl_Button* o, void* v) | |||||
| void DiskWriterPluginGUI::cb_Record(Fl_Button* o, void* v) | void DiskWriterPluginGUI::cb_Record(Fl_Button* o, void* v) | ||||
| { ((DiskWriterPluginGUI*)(o->parent()))->cb_Record_i(o,v); } | { ((DiskWriterPluginGUI*)(o->parent()))->cb_Record_i(o,v); } | ||||
| inline void DiskWriterPluginGUI::cb_16bits_i(Fl_Button* o, void* v) | |||||
| { | |||||
| m_GUICH->Set("BitsPerSample",16); | |||||
| } | |||||
| void DiskWriterPluginGUI::cb_16bits(Fl_Button* o, void* v) | |||||
| { ((DiskWriterPluginGUI*)(o->parent()))->cb_16bits_i(o,v); } | |||||
| inline void DiskWriterPluginGUI::cb_24bits_i(Fl_Button* o, void* v) | |||||
| { | |||||
| m_GUICH->Set("BitsPerSample",24); | |||||
| } | |||||
| void DiskWriterPluginGUI::cb_24bits(Fl_Button* o, void* v) | |||||
| { ((DiskWriterPluginGUI*)(o->parent()))->cb_24bits_i(o,v); } | |||||
| inline void DiskWriterPluginGUI::cb_32bits_i(Fl_Button* o, void* v) | |||||
| { | |||||
| m_GUICH->Set("BitsPerSample",32); | |||||
| } | |||||
| void DiskWriterPluginGUI::cb_32bits(Fl_Button* o, void* v) | |||||
| { ((DiskWriterPluginGUI*)(o->parent()))->cb_32bits_i(o,v); } | |||||
| const string DiskWriterPluginGUI::GetHelpText(const string &loc){ | const string DiskWriterPluginGUI::GetHelpText(const string &loc){ | ||||
| return string("") | return string("") | ||||
| + "One way of recording your creations to disk. First open a file\n" | + "One way of recording your creations to disk. First open a file\n" | ||||
| @@ -20,6 +20,7 @@ | |||||
| #include <FL/Fl_Button.H> | #include <FL/Fl_Button.H> | ||||
| #include "DiskWriterPlugin.h" | #include "DiskWriterPlugin.h" | ||||
| #include "../SpiralPluginGUI.h" | #include "../SpiralPluginGUI.h" | ||||
| #include "../Widgets/Fl_LED_Button.H" | |||||
| #ifndef DISK_WRITER_GUI_H | #ifndef DISK_WRITER_GUI_H | ||||
| #define DISK_WRITER_GUI_H | #define DISK_WRITER_GUI_H | ||||
| @@ -39,12 +40,23 @@ private: | |||||
| Fl_Button *Open; | Fl_Button *Open; | ||||
| Fl_Button *Record; | Fl_Button *Record; | ||||
| Fl_LED_Button *m_16bits; | |||||
| Fl_LED_Button *m_24bits; | |||||
| Fl_LED_Button *m_32bits; | |||||
| //// Callbacks //// | //// Callbacks //// | ||||
| inline void cb_Record_i(Fl_Button* o, void* v); | inline void cb_Record_i(Fl_Button* o, void* v); | ||||
| static void cb_Record(Fl_Button* o, void* v); | static void cb_Record(Fl_Button* o, void* v); | ||||
| inline void cb_Open_i(Fl_Button* o, void* v); | inline void cb_Open_i(Fl_Button* o, void* v); | ||||
| static void cb_Open(Fl_Button* o, void* v); | static void cb_Open(Fl_Button* o, void* v); | ||||
| inline void cb_16bits_i(Fl_Button* o, void* v); | |||||
| static void cb_16bits(Fl_Button* o, void* v); | |||||
| inline void cb_24bits_i(Fl_Button* o, void* v); | |||||
| static void cb_24bits(Fl_Button* o, void* v); | |||||
| inline void cb_32bits_i(Fl_Button* o, void* v); | |||||
| static void cb_32bits(Fl_Button* o, void* v); | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| @@ -45,6 +45,7 @@ HEADERS = DiskWriterPlugin.h \ | |||||
| ../../ChannelHandler.h \ | ../../ChannelHandler.h \ | ||||
| ../../Sample.h \ | ../../Sample.h \ | ||||
| ../../RiffWav.h \ | ../../RiffWav.h \ | ||||
| ../Widgets/Fl_LED_Button.H \ | |||||
| ../../../GUI/Widgets/SpiralGUI.H | ../../../GUI/Widgets/SpiralGUI.H | ||||
| SOURCES = DiskWriterPlugin.C \ | SOURCES = DiskWriterPlugin.C \ | ||||
| DiskWriterPluginGUI.C \ | DiskWriterPluginGUI.C \ | ||||
| @@ -53,6 +54,7 @@ SOURCES = DiskWriterPlugin.C \ | |||||
| ../../ChannelHandler.C \ | ../../ChannelHandler.C \ | ||||
| ../../Sample.C \ | ../../Sample.C \ | ||||
| ../../RiffWav.C \ | ../../RiffWav.C \ | ||||
| ../Widgets/Fl_LED_Button.cxx \ | |||||
| ../../../GUI/Widgets/SpiralGUI.C | ../../../GUI/Widgets/SpiralGUI.C | ||||
| OBJECTS = DiskWriterPlugin.o \ | OBJECTS = DiskWriterPlugin.o \ | ||||
| DiskWriterPluginGUI.o \ | DiskWriterPluginGUI.o \ | ||||
| @@ -61,6 +63,7 @@ OBJECTS = DiskWriterPlugin.o \ | |||||
| ../../ChannelHandler.o \ | ../../ChannelHandler.o \ | ||||
| ../../Sample.o \ | ../../Sample.o \ | ||||
| ../../RiffWav.o \ | ../../RiffWav.o \ | ||||
| ../Widgets/Fl_LED_Button.o \ | |||||
| ../../../GUI/Widgets/SpiralGUI.o | ../../../GUI/Widgets/SpiralGUI.o | ||||
| INTERFACES = | INTERFACES = | ||||
| UICDECLS = | UICDECLS = | ||||
| @@ -36,11 +36,27 @@ const int HEADERLEN = (4+24+8); | |||||
| #if __BYTE_ORDER == BIG_ENDIAN | #if __BYTE_ORDER == BIG_ENDIAN | ||||
| #define SWAPSHORT(a) (a)=(((a)<<8)|(((a)>>8)&0xff)) | #define SWAPSHORT(a) (a)=(((a)<<8)|(((a)>>8)&0xff)) | ||||
| #define SWAPINT(a) (a)=(((a)&0x000000ff)<<24)|(((a)&0x0000ff00)<<8)|(((a)&0x00ff0000)>>8)|(((a)&0xff000000)>>24) | #define SWAPINT(a) (a)=(((a)&0x000000ff)<<24)|(((a)&0x0000ff00)<<8)|(((a)&0x00ff0000)>>8)|(((a)&0xff000000)>>24) | ||||
| #define SWAPFLOAT(a) swap_be_to_le_float(&a) | |||||
| #else | #else | ||||
| #define SWAPSHORT(a) | #define SWAPSHORT(a) | ||||
| #define SWAPINT(a) | #define SWAPINT(a) | ||||
| #define SWAPFLOAT(a) | |||||
| #endif | #endif | ||||
| static void swap_be_to_le_float(float *a) | |||||
| { | |||||
| float tmp; | |||||
| char *src, *dst; | |||||
| src = (char*)a; | |||||
| dst = (char*)&tmp; | |||||
| dst[0] = src[3]; | |||||
| dst[1] = src[2]; | |||||
| dst[2] = src[1]; | |||||
| dst[3] = src[0]; | |||||
| *a = tmp; | |||||
| } | |||||
| int WavFile::Open(string FileName, Mode mode, Channels channels) | int WavFile::Open(string FileName, Mode mode, Channels channels) | ||||
| { | { | ||||
| if (m_Stream!=NULL) | if (m_Stream!=NULL) | ||||
| @@ -85,7 +101,7 @@ int WavFile::Open(string FileName, Mode mode, Channels channels) | |||||
| else m_Header.FmtChannels=1; | else m_Header.FmtChannels=1; | ||||
| m_Header.FmtSamplerate=WavFile::m_Samplerate; | m_Header.FmtSamplerate=WavFile::m_Samplerate; | ||||
| m_Header.FmtBitsPerSample=16; | |||||
| m_Header.FmtBitsPerSample=WavFile::m_BitsPerSample; | |||||
| m_Header.FmtBlockAlign=m_Header.FmtChannels*m_Header.FmtBitsPerSample/8; | m_Header.FmtBlockAlign=m_Header.FmtChannels*m_Header.FmtBitsPerSample/8; | ||||
| m_Header.FmtBytesPerSec=m_Header.FmtSamplerate*m_Header.FmtBlockAlign; | m_Header.FmtBytesPerSec=m_Header.FmtSamplerate*m_Header.FmtBlockAlign; | ||||
| @@ -125,6 +141,9 @@ int WavFile::Open(string FileName, Mode mode, Channels channels) | |||||
| SWAPSHORT(m_Header.FmtBlockAlign); | SWAPSHORT(m_Header.FmtBlockAlign); | ||||
| SWAPSHORT(m_Header.FmtBitsPerSample); | SWAPSHORT(m_Header.FmtBitsPerSample); | ||||
| WavFile::m_BitsPerSample=m_Header.FmtBitsPerSample; | |||||
| WavFile::m_Samplerate=m_Header.FmtSamplerate; | |||||
| #ifdef TRACE_OUT | #ifdef TRACE_OUT | ||||
| cerr<<FileName<<endl; | cerr<<FileName<<endl; | ||||
| cerr<<"RiffFileLength "<<m_Header.RiffFileLength<<endl; | cerr<<"RiffFileLength "<<m_Header.RiffFileLength<<endl; | ||||
| @@ -211,23 +230,58 @@ int WavFile::Save(Sample &data) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| // convert to integer for saving | |||||
| short *temp=new short[data.GetLength()]; | |||||
| for (int n=0; n<data.GetLength(); n++) | |||||
| { | |||||
| //clip | |||||
| float v=data[n]; | |||||
| if (v<-1) v=-1; if (v>1) v=1; | |||||
| temp[n]=(short)(v*SHRT_MAX); | |||||
| SWAPSHORT(temp[n]); | |||||
| int Bps = m_Header.FmtBitsPerSample/8; | |||||
| // convert to integer for saving | |||||
| if (Bps == 2) { | |||||
| short *temp=new short[data.GetLength()]; | |||||
| for (int n=0; n<data.GetLength(); n++) | |||||
| { | |||||
| //clip | |||||
| float v=data[n]; | |||||
| if (v<-1) v=-1; if (v>1) v=1; | |||||
| temp[n]=(short)(v*SHRT_MAX); | |||||
| SWAPSHORT(temp[n]); | |||||
| } | |||||
| m_DataHeader.DataLengthBytes+=data.GetLength()*Bps; | |||||
| fwrite(temp,sizeof(&temp),data.GetLength()/Bps,m_Stream); | |||||
| // leak! | |||||
| delete[] temp; | |||||
| } else if ((Bps == 3)) { | |||||
| int *temp=new int[data.GetLength()]; | |||||
| for (int n=0; n<data.GetLength(); n++) | |||||
| { | |||||
| //clip | |||||
| float v=data[n]; | |||||
| if (v<-1) v=-1; if (v>1) v=1; | |||||
| temp[n]=(int)(v*INT_MAX); | |||||
| SWAPINT(temp[n]); | |||||
| } | |||||
| m_DataHeader.DataLengthBytes+=data.GetLength()*Bps; | |||||
| fwrite(temp,sizeof(&temp),data.GetLength()/Bps,m_Stream); | |||||
| // leak! | |||||
| delete[] temp; | |||||
| } else if ((Bps == 4)) { | |||||
| float *temp=new float[data.GetLength()]; | |||||
| for (int n=0; n<data.GetLength(); n++) | |||||
| { | |||||
| //clip | |||||
| float v=data[n]; | |||||
| if (v<-1.0) v=-1.0; if (v>1.0) v=1.0; | |||||
| temp[n]=v; | |||||
| SWAPFLOAT(temp[n]); | |||||
| } | |||||
| m_DataHeader.DataLengthBytes+=data.GetLength()*Bps; | |||||
| fwrite(temp,sizeof(&temp),data.GetLength()/Bps,m_Stream); | |||||
| // leak! | |||||
| delete[] temp; | |||||
| } | } | ||||
| m_DataHeader.DataLengthBytes+=data.GetLength()*2; | |||||
| fwrite(temp,sizeof(&temp),data.GetLength()/2,m_Stream); | |||||
| // leak! | |||||
| delete[] temp; | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| @@ -245,24 +299,20 @@ int WavFile::Save(short *data, int Bytes) | |||||
| int WavFile::GetSize() | int WavFile::GetSize() | ||||
| { | { | ||||
| if (m_Header.FmtBitsPerSample!=8 && m_Header.FmtBitsPerSample!=16) | |||||
| int Bps = m_Header.FmtBitsPerSample/8; | |||||
| if ((Bps<1) || (Bps>3)) | |||||
| { | { | ||||
| cerr<<"WavFile Warning: FmtBitsPerSample="<<m_Header.FmtBitsPerSample<<" (can't cope, treating as 16)"<<endl; | cerr<<"WavFile Warning: FmtBitsPerSample="<<m_Header.FmtBitsPerSample<<" (can't cope, treating as 16)"<<endl; | ||||
| m_Header.FmtBitsPerSample=16; | m_Header.FmtBitsPerSample=16; | ||||
| Bps=2; | |||||
| } | } | ||||
| int ret=0; | int ret=0; | ||||
| if (m_Header.FmtBitsPerSample==8) | |||||
| { | |||||
| if (IsStereo()) ret=m_DataHeader.DataLengthBytes/2; | |||||
| else ret=m_DataHeader.DataLengthBytes; | |||||
| } | |||||
| if (IsStereo()) | |||||
| ret=m_DataHeader.DataLengthBytes/(Bps*2); | |||||
| else | else | ||||
| { | |||||
| if (IsStereo()) ret=m_DataHeader.DataLengthBytes/4; | |||||
| else ret=m_DataHeader.DataLengthBytes/2; | |||||
| } | |||||
| ret=m_DataHeader.DataLengthBytes/Bps; | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -59,7 +59,7 @@ struct DataHeader | |||||
| class WavFile | class WavFile | ||||
| { | { | ||||
| public: | public: | ||||
| WavFile() : m_Stream(NULL), m_Samplerate(44100), m_DataStart(0) {} | |||||
| WavFile() : m_Stream(NULL), m_Samplerate(44100), m_BitsPerSample(16), m_DataStart(0) {} | |||||
| ~WavFile() {Close();} | ~WavFile() {Close();} | ||||
| enum Mode{READ,WRITE}; | enum Mode{READ,WRITE}; | ||||
| @@ -77,6 +77,8 @@ public: | |||||
| bool Recording() {return (m_Stream!=NULL);} | bool Recording() {return (m_Stream!=NULL);} | ||||
| void SetSamplerate(int s) { m_Samplerate=s; } | void SetSamplerate(int s) { m_Samplerate=s; } | ||||
| int GetSamplerate() { return m_Header.FmtSamplerate; } | int GetSamplerate() { return m_Header.FmtSamplerate; } | ||||
| void SetBitsPerSample(int s) { m_BitsPerSample=s; } | |||||
| int GetBitsPerSample() { return m_Header.FmtBitsPerSample; } | |||||
| bool IsStereo() { return (m_Header.FmtChannels==2); } | bool IsStereo() { return (m_Header.FmtChannels==2); } | ||||
| bool IsOpen() { return m_Stream!=NULL; } | bool IsOpen() { return m_Stream!=NULL; } | ||||
| @@ -84,6 +86,7 @@ private: | |||||
| FILE *m_Stream; | FILE *m_Stream; | ||||
| int m_Samplerate; | int m_Samplerate; | ||||
| int m_BitsPerSample; | |||||
| long m_DataStart; | long m_DataStart; | ||||
| long m_CurSeekPos; | long m_CurSeekPos; | ||||