| @@ -74,15 +74,18 @@ DiskWriterPlugin::DiskWriterPlugin() : | |||
| m_Recording(false) | |||
| { | |||
| 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.NumOutputs=0; | |||
| m_PluginInfo.PortTips.push_back("Left Out"); | |||
| m_PluginInfo.PortTips.push_back("Right Out"); | |||
| m_PluginInfo.PortTips.push_back("Record Controller"); | |||
| m_GUIArgs.BitsPerSample = 16; | |||
| m_AudioCH->RegisterData("Filename",ChannelHandler::INPUT,m_GUIArgs.Name,256); | |||
| m_AudioCH->Register("BitsPerSample",&m_GUIArgs.BitsPerSample,ChannelHandler::INPUT); | |||
| } | |||
| DiskWriterPlugin::~DiskWriterPlugin() | |||
| @@ -107,12 +110,12 @@ SpiralGUIType *DiskWriterPlugin::CreateGUI() | |||
| void DiskWriterPlugin::Execute() | |||
| { | |||
| int Bps = m_GUIArgs.BitsPerSample/8; | |||
| if(m_Recording && m_Wav.IsOpen()) | |||
| { | |||
| int on=0; | |||
| float t; | |||
| short Buffer[host->BUFSIZE*2]; | |||
| short Buffer[host->BUFSIZE*Bps]; | |||
| for (int n=0; n<host->BUFSIZE; n++) | |||
| { | |||
| @@ -130,8 +133,8 @@ void DiskWriterPlugin::Execute() | |||
| 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) { | |||
| 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); | |||
| break; | |||
| case CLOSEWAV : m_Wav.Close(); break; | |||
| @@ -40,6 +40,7 @@ public: | |||
| struct GUIArgs | |||
| { | |||
| char Name[256]; | |||
| int BitsPerSample; | |||
| }; | |||
| private: | |||
| @@ -25,7 +25,23 @@ using namespace std; | |||
| DiskWriterPluginGUI::DiskWriterPluginGUI(int w, int h, SpiralPlugin *o, ChannelHandler *ch,const HostInfo *Info) : | |||
| 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->box (FL_PLASTIC_UP_BOX); | |||
| Open->color (Info->GUI_COLOUR); | |||
| @@ -33,7 +49,7 @@ SpiralPluginGUI(w,h,o,ch) | |||
| Open->labelsize(10); | |||
| 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->box (FL_PLASTIC_UP_BOX); | |||
| 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); | |||
| } | |||
| } | |||
| void DiskWriterPluginGUI::cb_Open(Fl_Button* o, void* 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) | |||
| { ((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){ | |||
| return string("") | |||
| + "One way of recording your creations to disk. First open a file\n" | |||
| @@ -20,6 +20,7 @@ | |||
| #include <FL/Fl_Button.H> | |||
| #include "DiskWriterPlugin.h" | |||
| #include "../SpiralPluginGUI.h" | |||
| #include "../Widgets/Fl_LED_Button.H" | |||
| #ifndef DISK_WRITER_GUI_H | |||
| #define DISK_WRITER_GUI_H | |||
| @@ -39,12 +40,23 @@ private: | |||
| Fl_Button *Open; | |||
| Fl_Button *Record; | |||
| Fl_LED_Button *m_16bits; | |||
| Fl_LED_Button *m_24bits; | |||
| Fl_LED_Button *m_32bits; | |||
| //// Callbacks //// | |||
| inline void cb_Record_i(Fl_Button* o, void* v); | |||
| static void cb_Record(Fl_Button* o, void* v); | |||
| inline void cb_Open_i(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 | |||
| @@ -45,6 +45,7 @@ HEADERS = DiskWriterPlugin.h \ | |||
| ../../ChannelHandler.h \ | |||
| ../../Sample.h \ | |||
| ../../RiffWav.h \ | |||
| ../Widgets/Fl_LED_Button.H \ | |||
| ../../../GUI/Widgets/SpiralGUI.H | |||
| SOURCES = DiskWriterPlugin.C \ | |||
| DiskWriterPluginGUI.C \ | |||
| @@ -53,6 +54,7 @@ SOURCES = DiskWriterPlugin.C \ | |||
| ../../ChannelHandler.C \ | |||
| ../../Sample.C \ | |||
| ../../RiffWav.C \ | |||
| ../Widgets/Fl_LED_Button.cxx \ | |||
| ../../../GUI/Widgets/SpiralGUI.C | |||
| OBJECTS = DiskWriterPlugin.o \ | |||
| DiskWriterPluginGUI.o \ | |||
| @@ -61,6 +63,7 @@ OBJECTS = DiskWriterPlugin.o \ | |||
| ../../ChannelHandler.o \ | |||
| ../../Sample.o \ | |||
| ../../RiffWav.o \ | |||
| ../Widgets/Fl_LED_Button.o \ | |||
| ../../../GUI/Widgets/SpiralGUI.o | |||
| INTERFACES = | |||
| UICDECLS = | |||
| @@ -36,11 +36,27 @@ const int HEADERLEN = (4+24+8); | |||
| #if __BYTE_ORDER == BIG_ENDIAN | |||
| #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 SWAPFLOAT(a) swap_be_to_le_float(&a) | |||
| #else | |||
| #define SWAPSHORT(a) | |||
| #define SWAPINT(a) | |||
| #define SWAPFLOAT(a) | |||
| #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) | |||
| { | |||
| if (m_Stream!=NULL) | |||
| @@ -85,7 +101,7 @@ int WavFile::Open(string FileName, Mode mode, Channels channels) | |||
| else m_Header.FmtChannels=1; | |||
| 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.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.FmtBitsPerSample); | |||
| WavFile::m_BitsPerSample=m_Header.FmtBitsPerSample; | |||
| WavFile::m_Samplerate=m_Header.FmtSamplerate; | |||
| #ifdef TRACE_OUT | |||
| cerr<<FileName<<endl; | |||
| cerr<<"RiffFileLength "<<m_Header.RiffFileLength<<endl; | |||
| @@ -211,23 +230,58 @@ int WavFile::Save(Sample &data) | |||
| 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; | |||
| } | |||
| @@ -245,24 +299,20 @@ int WavFile::Save(short *data, int Bytes) | |||
| 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; | |||
| m_Header.FmtBitsPerSample=16; | |||
| Bps=2; | |||
| } | |||
| 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 | |||
| { | |||
| if (IsStereo()) ret=m_DataHeader.DataLengthBytes/4; | |||
| else ret=m_DataHeader.DataLengthBytes/2; | |||
| } | |||
| ret=m_DataHeader.DataLengthBytes/Bps; | |||
| return ret; | |||
| } | |||
| @@ -59,7 +59,7 @@ struct DataHeader | |||
| class WavFile | |||
| { | |||
| 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();} | |||
| enum Mode{READ,WRITE}; | |||
| @@ -77,6 +77,8 @@ public: | |||
| bool Recording() {return (m_Stream!=NULL);} | |||
| void SetSamplerate(int s) { m_Samplerate=s; } | |||
| 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 IsOpen() { return m_Stream!=NULL; } | |||
| @@ -84,6 +86,7 @@ private: | |||
| FILE *m_Stream; | |||
| int m_Samplerate; | |||
| int m_BitsPerSample; | |||
| long m_DataStart; | |||
| long m_CurSeekPos; | |||