diff --git a/.gitignore b/.gitignore index 185edb9266c96415826b5c90fc37ad3a191b7673..85836339d2da43bc7c7a2e3a71c9cbb6cafdee84 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ JuceLibraryCode/jucer/Builds/Linux/build Builds/Linux/build/data Builds/Linux/build/savedState.xml Builds/Linux/build/windowState.xml +Builds/Linux/build/Data diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index 151287fe10235e5717abf93f8105602401514331..ee7bed61056a5eae174ad1d68e41fd951af4ad51 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -19,7 +19,7 @@ ifeq ($(CONFIG),Debug) OUTDIR := build CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I "/usr/include" -I "/usr/include/freetype2" CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 - CXXFLAGS += $(CFLAGS) -export-dynamic + CXXFLAGS += $(CFLAGS) -export-dynamic -pg LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -L"/usr/X11R6/lib/" -L"../../JuceLibraryCode/bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -lftdi -lftgl LDDEPS := RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I "/usr/include" -I "/usr/include/freetype2" @@ -34,7 +34,7 @@ ifeq ($(CONFIG),Release) OUTDIR := build CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I "/usr/include" -I "/usr/include/freetype2" CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 - CXXFLAGS += $(CFLAGS) -export-dynamic + CXXFLAGS += $(CFLAGS) -export-dynamic -pg LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -L"/usr/X11R6/lib/" -L"../../JuceLibraryCode/bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -lftdi -lftgl LDDEPS := RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I "/usr/include" -I "/usr/include/freetype2" @@ -63,17 +63,30 @@ OBJECTS := \ $(OBJDIR)/RootFinder_239a995f.o \ $(OBJDIR)/State_22979684.o \ $(OBJDIR)/AudioComponent_521bd9c9.o \ + $(OBJDIR)/Parameter_ae008024.o \ + $(OBJDIR)/SpikeDisplayNode_9c52e4ad.o \ $(OBJDIR)/WiFiOutput_fa464ec5.o \ $(OBJDIR)/LfpDisplayNode_30ef22fd.o \ $(OBJDIR)/Merger_2f90542e.o \ $(OBJDIR)/Splitter_6e27a57b.o \ + $(OBJDIR)/StereotrodePlot_4710b8f1.o \ + $(OBJDIR)/ElectrodePlot_7a206ec4.o \ + $(OBJDIR)/BaseUIElement_ec903c4d.o \ + $(OBJDIR)/GenericAxes_d802ed92.o \ + $(OBJDIR)/PlotUtils_9ef52686.o \ + $(OBJDIR)/ProjectionAxes_7c67c3e8.o \ + $(OBJDIR)/TetrodePlot_b42fd798.o \ + $(OBJDIR)/WaveAxes_8adc45d2.o \ + $(OBJDIR)/SpikeObject_24e8c655.o \ + $(OBJDIR)/SpikeDisplayCanvas_b208ff6e.o \ $(OBJDIR)/DataWindow_83ce6754.o \ $(OBJDIR)/LfpDisplayCanvas_4a58e87e.o \ $(OBJDIR)/OpenGLCanvas_3c775a41.o \ $(OBJDIR)/SpikeDetector_300d85e7.o \ - $(OBJDIR)/FileReader_18023b0e.o \ $(OBJDIR)/AudioNode_94606ff3.o \ $(OBJDIR)/EventNode_95c842b7.o \ + $(OBJDIR)/SpikeDisplayEditor_e1812c1.o \ + $(OBJDIR)/VisualizerEditor_3672b003.o \ $(OBJDIR)/MergerEditor_d1fcc0df.o \ $(OBJDIR)/ImageIcon_c89b23a6.o \ $(OBJDIR)/WiFiOutputEditor_1d3ba5bb.o \ @@ -107,7 +120,6 @@ OBJECTS := \ $(OBJDIR)/CustomLookAndFeel_53a8fcdb.o \ $(OBJDIR)/InfoLabel_a2051bf4.o \ $(OBJDIR)/DataViewport_2cf95d2c.o \ - $(OBJDIR)/Configuration_6915cd84.o \ $(OBJDIR)/MessageCenter_748a1cca.o \ $(OBJDIR)/ControlPanel_a895ede3.o \ $(OBJDIR)/UIComponent_d667ba37.o \ @@ -234,6 +246,16 @@ $(OBJDIR)/AudioComponent_521bd9c9.o: ../../Source/Audio/AudioComponent.cpp @echo "Compiling AudioComponent.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/Parameter_ae008024.o: ../../Source/Processors/Parameter.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling Parameter.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/SpikeDisplayNode_9c52e4ad.o: ../../Source/Processors/SpikeDisplayNode.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling SpikeDisplayNode.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/WiFiOutput_fa464ec5.o: ../../Source/Processors/WiFiOutput.cpp -@mkdir -p $(OBJDIR) @echo "Compiling WiFiOutput.cpp" @@ -254,6 +276,56 @@ $(OBJDIR)/Splitter_6e27a57b.o: ../../Source/Processors/Utilities/Splitter.cpp @echo "Compiling Splitter.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/StereotrodePlot_4710b8f1.o: ../../Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling StereotrodePlot.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/ElectrodePlot_7a206ec4.o: ../../Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling ElectrodePlot.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/BaseUIElement_ec903c4d.o: ../../Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling BaseUIElement.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/GenericAxes_d802ed92.o: ../../Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling GenericAxes.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/PlotUtils_9ef52686.o: ../../Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling PlotUtils.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/ProjectionAxes_7c67c3e8.o: ../../Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling ProjectionAxes.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/TetrodePlot_b42fd798.o: ../../Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling TetrodePlot.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/WaveAxes_8adc45d2.o: ../../Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling WaveAxes.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/SpikeObject_24e8c655.o: ../../Source/Processors/Visualization/SpikeObject.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling SpikeObject.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/SpikeDisplayCanvas_b208ff6e.o: ../../Source/Processors/Visualization/SpikeDisplayCanvas.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling SpikeDisplayCanvas.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/DataWindow_83ce6754.o: ../../Source/Processors/Visualization/DataWindow.cpp -@mkdir -p $(OBJDIR) @echo "Compiling DataWindow.cpp" @@ -274,11 +346,6 @@ $(OBJDIR)/SpikeDetector_300d85e7.o: ../../Source/Processors/SpikeDetector.cpp @echo "Compiling SpikeDetector.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" -$(OBJDIR)/FileReader_18023b0e.o: ../../Source/Processors/FileReader.cpp - -@mkdir -p $(OBJDIR) - @echo "Compiling FileReader.cpp" - @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" - $(OBJDIR)/AudioNode_94606ff3.o: ../../Source/Processors/AudioNode.cpp -@mkdir -p $(OBJDIR) @echo "Compiling AudioNode.cpp" @@ -289,6 +356,16 @@ $(OBJDIR)/EventNode_95c842b7.o: ../../Source/Processors/EventNode.cpp @echo "Compiling EventNode.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/SpikeDisplayEditor_e1812c1.o: ../../Source/Processors/Editors/SpikeDisplayEditor.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling SpikeDisplayEditor.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + +$(OBJDIR)/VisualizerEditor_3672b003.o: ../../Source/Processors/Editors/VisualizerEditor.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling VisualizerEditor.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/MergerEditor_d1fcc0df.o: ../../Source/Processors/Editors/MergerEditor.cpp -@mkdir -p $(OBJDIR) @echo "Compiling MergerEditor.cpp" @@ -454,11 +531,6 @@ $(OBJDIR)/DataViewport_2cf95d2c.o: ../../Source/UI/DataViewport.cpp @echo "Compiling DataViewport.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" -$(OBJDIR)/Configuration_6915cd84.o: ../../Source/UI/Configuration.cpp - -@mkdir -p $(OBJDIR) - @echo "Compiling Configuration.cpp" - @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" - $(OBJDIR)/MessageCenter_748a1cca.o: ../../Source/UI/MessageCenter.cpp -@mkdir -p $(OBJDIR) @echo "Compiling MessageCenter.cpp" diff --git a/Builds/Linux/build/data_stream_16ch b/Builds/Linux/build/data_stream_16ch new file mode 100644 index 0000000000000000000000000000000000000000..de0196c18569705d7b26fdfa2d22b14ef5f92436 Binary files /dev/null and b/Builds/Linux/build/data_stream_16ch differ diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj index e6dfea255137553f617920d46d8f9d8ae4730225..e402638d5a9032e0194b606679806d7674a52d68 100644 --- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj @@ -37,17 +37,30 @@ 8E138283FC265B58D252AAC3 = { isa = PBXBuildFile; fileRef = F4A53064BA75472765338C1D; }; EE1DC0B09AE0727BC7A5A99C = { isa = PBXBuildFile; fileRef = 0D20C3399D0492771F7A808A; }; 4ACF816CB5CDB285D8005AB8 = { isa = PBXBuildFile; fileRef = F74662D3D82975EDB5AD42E0; }; + 717D108DC8B2379D556C4B2F = { isa = PBXBuildFile; fileRef = 751C52F2BEA7F1328ED13333; }; + 1F67A9ACD509FB4DC5A633DF = { isa = PBXBuildFile; fileRef = 4AEDD076CCA918481C6F9CF2; }; B992DDBFF8928A985EEE1557 = { isa = PBXBuildFile; fileRef = 268005410FB62BCB9099A762; }; F1268EC5E783EC8ECEBCA5D3 = { isa = PBXBuildFile; fileRef = 5935F823A2EE45AC36A0201F; }; 4A00153E1E69A74BC6B7D8A6 = { isa = PBXBuildFile; fileRef = 3973173C7FA07073B4F86B29; }; 5F13B8FFB1584BFF6C05AD39 = { isa = PBXBuildFile; fileRef = 9A47B52E5E1CD17DC9C72B53; }; + B11D72764B1B17BF2B8C6E67 = { isa = PBXBuildFile; fileRef = C92B3F413B0F24752ADE6730; }; + 938FC2F779C2CF4B8C7ECFFE = { isa = PBXBuildFile; fileRef = 3BB44F767E701E3642435FA0; }; + 55A240CCFCD604CA8DF8FC8C = { isa = PBXBuildFile; fileRef = 41591F74A761BAC908FA8AD8; }; + 8025F04ED261C7F7D2DC0F06 = { isa = PBXBuildFile; fileRef = 24C6D768C87E1C42C644C4BD; }; + 49F046C8BE137BF77338DD7B = { isa = PBXBuildFile; fileRef = B195AD6CEB9B6E3625C8D087; }; + 566E42D2B7105CFB4DB45170 = { isa = PBXBuildFile; fileRef = 2FA2FA826CBAD9C639A61E4A; }; + 0DDC562EC2B04A26AE6CBB2B = { isa = PBXBuildFile; fileRef = FBB9A423728922E96F55074F; }; + BCD7C4797178C8EF65CDC2D7 = { isa = PBXBuildFile; fileRef = 9F208A66C09E80D14F087CB1; }; + 9145D84C7D665BCAFE698432 = { isa = PBXBuildFile; fileRef = E7247F5EE9588903C924994F; }; + 7659F31912D12C91E9554909 = { isa = PBXBuildFile; fileRef = 7A9A31FC1AE8FB238FAE995E; }; 9D687F73F2FD2462C5D5588C = { isa = PBXBuildFile; fileRef = ED179D5A10DD051DDB3ECB8B; }; B13883377C9316B9603336B4 = { isa = PBXBuildFile; fileRef = 2E96DA81EE37A0ECE471A928; }; 073B178E7EF1759BA0AACCCE = { isa = PBXBuildFile; fileRef = 0C5335B0E57C9DC92FC57E5F; }; 4BE0DDA01B73223EF0BD934A = { isa = PBXBuildFile; fileRef = 3DD0741FCFBC7563EC722D9B; }; - 6656467170D2822949BD2F7F = { isa = PBXBuildFile; fileRef = 5AC4DD48CCB1AB4936A2DE4A; }; 08B501E0D7764C6B613AF529 = { isa = PBXBuildFile; fileRef = B7750B27E4F3748ECCCCF69D; }; 9CBA3837CC8CAA03A03F2D9C = { isa = PBXBuildFile; fileRef = FA57CE4F63FF1592D6B3F9B5; }; + DD22A06702F4CF995893DD5C = { isa = PBXBuildFile; fileRef = F0B09605D4108F0F94EF3B57; }; + F4CEF74DDCD7EFA0891249B5 = { isa = PBXBuildFile; fileRef = 9A3976537C96B39716B5312D; }; 93A3E6284F2DAED3F491332B = { isa = PBXBuildFile; fileRef = AD73EA6B24378294003DC2D0; }; CB77C89226102EF30F85E3EC = { isa = PBXBuildFile; fileRef = 544DA1EF90EBBDB6FF2DE0A5; }; A126280FF39A61DEFD3ABFE5 = { isa = PBXBuildFile; fileRef = 2B11714BCE362D4EA7E377F5; }; @@ -81,7 +94,6 @@ 13457B3248E7646270A4FF88 = { isa = PBXBuildFile; fileRef = A32D8455B95FD230EBFD7891; }; D060C0893EDAE6CBC86A5FE2 = { isa = PBXBuildFile; fileRef = AA00883DC021E36B7EFDAC43; }; E36C0018635A85E09D4EDE01 = { isa = PBXBuildFile; fileRef = B977C2809B309C8038CB5D95; }; - 4BE24CDF92926150BFC83ED2 = { isa = PBXBuildFile; fileRef = 2F53BB2693AA5F1C2F27AF7C; }; C170A763D33146C74ED4CE4B = { isa = PBXBuildFile; fileRef = EEDA71600D817BF9444FE3E7; }; 116BB2F62451986C75586F9D = { isa = PBXBuildFile; fileRef = 5AB4A3A63B9FDEAB09EEC9C8; }; 1F301384375DA0F3652C01DA = { isa = PBXBuildFile; fileRef = 2A78F719BAFBDCD63AE9A88A; }; @@ -119,6 +131,31 @@ C2A7939DF5ED600BBB2F30C4 = { isa = PBXFileReference; lastKnownFileType = file; name = "silkscreen-serialized"; path = "../../Resources/Fonts/silkscreen-serialized"; sourceTree = SOURCE_ROOT; }; F8CAE2412B173788F325BD8B = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = silkscreen.ttf; path = ../../Resources/Fonts/silkscreen.ttf; sourceTree = SOURCE_ROOT; }; 363B59958615D35C5C948300 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "unibody-8.otf"; path = "../../Resources/Fonts/unibody-8.otf"; sourceTree = SOURCE_ROOT; }; + 4DB02C352236D9D030E01205 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-01.png"; path = "../../Resources/Images/Icons/RadioButtons-01.png"; sourceTree = SOURCE_ROOT; }; + EEAB043F90902D8F9D1102C2 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-02.png"; path = "../../Resources/Images/Icons/RadioButtons-02.png"; sourceTree = SOURCE_ROOT; }; + 8086EC3AFDEA802E0B43F19E = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-03.png"; path = "../../Resources/Images/Icons/RadioButtons-03.png"; sourceTree = SOURCE_ROOT; }; + 2171C4356B44D4CD6865E06B = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-04.png"; path = "../../Resources/Images/Icons/RadioButtons-04.png"; sourceTree = SOURCE_ROOT; }; + C25CAC3FC9AE387CD597DF37 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-05.png"; path = "../../Resources/Images/Icons/RadioButtons-05.png"; sourceTree = SOURCE_ROOT; }; + 59CAEFDE36164ABB19B3CA76 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_neutral-01.png"; path = "../../Resources/Images/Icons/RadioButtons_neutral-01.png"; sourceTree = SOURCE_ROOT; }; + E0587F61AD4A92C2661E5073 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_neutral-02.png"; path = "../../Resources/Images/Icons/RadioButtons_neutral-02.png"; sourceTree = SOURCE_ROOT; }; + 87F60F05136FEBD8A36AE670 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_neutral-03.png"; path = "../../Resources/Images/Icons/RadioButtons_neutral-03.png"; sourceTree = SOURCE_ROOT; }; + 1E849F999A8333FFF0B57C6D = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_neutral-04.png"; path = "../../Resources/Images/Icons/RadioButtons_neutral-04.png"; sourceTree = SOURCE_ROOT; }; + A5231F3D01B88C063D10026A = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_neutral-05.png"; path = "../../Resources/Images/Icons/RadioButtons_neutral-05.png"; sourceTree = SOURCE_ROOT; }; + 40A802FCEDFDE7B2FFEBDEA8 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected-01.png"; path = "../../Resources/Images/Icons/RadioButtons_selected-01.png"; sourceTree = SOURCE_ROOT; }; + 8A3AE5CF9D452810BA48A3EF = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected-02.png"; path = "../../Resources/Images/Icons/RadioButtons_selected-02.png"; sourceTree = SOURCE_ROOT; }; + B3CDC8825DAD5A7D75956726 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected-03.png"; path = "../../Resources/Images/Icons/RadioButtons_selected-03.png"; sourceTree = SOURCE_ROOT; }; + ED50AB550D058BEB30F12C7D = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected-04.png"; path = "../../Resources/Images/Icons/RadioButtons_selected-04.png"; sourceTree = SOURCE_ROOT; }; + 17E38F29BD6CBC490B5EF1B4 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected-05.png"; path = "../../Resources/Images/Icons/RadioButtons_selected-05.png"; sourceTree = SOURCE_ROOT; }; + D95C78F42494CD5995FBC15E = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-01.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-01.png"; sourceTree = SOURCE_ROOT; }; + 20B50BC2221C593AC67D80F8 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-02.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-02.png"; sourceTree = SOURCE_ROOT; }; + 771E8D912F94E52AF7E05F91 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-03.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-03.png"; sourceTree = SOURCE_ROOT; }; + CE771F502D1D710B28632E3A = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-04.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-04.png"; sourceTree = SOURCE_ROOT; }; + 05D0A12F2A850EEC48D5EDD4 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-05.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-05.png"; sourceTree = SOURCE_ROOT; }; + 8F8F55DD042F61BB213AFC0B = { isa = PBXFileReference; lastKnownFileType = image.png; name = noise_wave.png; path = ../../Resources/Images/Icons/noise_wave.png; sourceTree = SOURCE_ROOT; }; + 7C09194091360867C4CAB0E8 = { isa = PBXFileReference; lastKnownFileType = image.png; name = saw_wave.png; path = ../../Resources/Images/Icons/saw_wave.png; sourceTree = SOURCE_ROOT; }; + 126B0DE9B8D4E42DA7D57AAB = { isa = PBXFileReference; lastKnownFileType = image.png; name = sine_wave.png; path = ../../Resources/Images/Icons/sine_wave.png; sourceTree = SOURCE_ROOT; }; + BDFFB5B0A8E8A022C25D7FDB = { isa = PBXFileReference; lastKnownFileType = image.png; name = square_wave.png; path = ../../Resources/Images/Icons/square_wave.png; sourceTree = SOURCE_ROOT; }; + 3D20C932FB058CC20989B129 = { isa = PBXFileReference; lastKnownFileType = image.png; name = triangle_wave.png; path = ../../Resources/Images/Icons/triangle_wave.png; sourceTree = SOURCE_ROOT; }; 8E041C8C49F1A5B710CC812C = { isa = PBXFileReference; lastKnownFileType = image.png; name = wifi.png; path = ../../Resources/Images/Icons/wifi.png; sourceTree = SOURCE_ROOT; }; 2A1D9144C59B92B32483924B = { isa = PBXFileReference; lastKnownFileType = image.png; name = SourceDrop.png; path = ../../Resources/Images/Icons/SourceDrop.png; sourceTree = SOURCE_ROOT; }; D99F56FB46F631F67AF23F2C = { isa = PBXFileReference; lastKnownFileType = image.png; name = DefaultDataSource.png; path = ../../Resources/Images/Icons/DefaultDataSource.png; sourceTree = SOURCE_ROOT; }; @@ -180,6 +217,10 @@ E27B5891A52FDAB2B00901A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utilities.h; path = ../../Source/Dsp/Utilities.h; sourceTree = SOURCE_ROOT; }; F74662D3D82975EDB5AD42E0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioComponent.cpp; path = ../../Source/Audio/AudioComponent.cpp; sourceTree = SOURCE_ROOT; }; FA55B9FDE138CCB1F16BA905 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioComponent.h; path = ../../Source/Audio/AudioComponent.h; sourceTree = SOURCE_ROOT; }; + 751C52F2BEA7F1328ED13333 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Parameter.cpp; path = ../../Source/Processors/Parameter.cpp; sourceTree = SOURCE_ROOT; }; + 7B825983F25D8984E02F6FFB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Parameter.h; path = ../../Source/Processors/Parameter.h; sourceTree = SOURCE_ROOT; }; + 4AEDD076CCA918481C6F9CF2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayNode.cpp; path = ../../Source/Processors/SpikeDisplayNode.cpp; sourceTree = SOURCE_ROOT; }; + 671CC5EA3DF4F21E9A7E392B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayNode.h; path = ../../Source/Processors/SpikeDisplayNode.h; sourceTree = SOURCE_ROOT; }; 268005410FB62BCB9099A762 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WiFiOutput.cpp; path = ../../Source/Processors/WiFiOutput.cpp; sourceTree = SOURCE_ROOT; }; 32959675287F77DD9B7FA96B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WiFiOutput.h; path = ../../Source/Processors/WiFiOutput.h; sourceTree = SOURCE_ROOT; }; 5935F823A2EE45AC36A0201F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayNode.cpp; path = ../../Source/Processors/LfpDisplayNode.cpp; sourceTree = SOURCE_ROOT; }; @@ -188,6 +229,28 @@ 7977CAB4A151C41F4140FE1A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Merger.h; path = ../../Source/Processors/Utilities/Merger.h; sourceTree = SOURCE_ROOT; }; 9A47B52E5E1CD17DC9C72B53 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Splitter.cpp; path = ../../Source/Processors/Utilities/Splitter.cpp; sourceTree = SOURCE_ROOT; }; B92E8189F69E0B926C73B654 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Splitter.h; path = ../../Source/Processors/Utilities/Splitter.h; sourceTree = SOURCE_ROOT; }; + C92B3F413B0F24752ADE6730 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = StereotrodePlot.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp; sourceTree = SOURCE_ROOT; }; + FDD549F527C378CF36BDB8C7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StereotrodePlot.h; path = ../../Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h; sourceTree = SOURCE_ROOT; }; + 3BB44F767E701E3642435FA0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ElectrodePlot.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp; sourceTree = SOURCE_ROOT; }; + 1AAF672654B16469EFB41AC2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ElectrodePlot.h; path = ../../Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h; sourceTree = SOURCE_ROOT; }; + 41591F74A761BAC908FA8AD8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = BaseUIElement.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp; sourceTree = SOURCE_ROOT; }; + 9C8EA29582DBFF6E5A14B8A3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BaseUIElement.h; path = ../../Source/Processors/Visualization/SpikePlotting/BaseUIElement.h; sourceTree = SOURCE_ROOT; }; + 24C6D768C87E1C42C644C4BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GenericAxes.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp; sourceTree = SOURCE_ROOT; }; + BCBB865ED53E8AFD278D1A53 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GenericAxes.h; path = ../../Source/Processors/Visualization/SpikePlotting/GenericAxes.h; sourceTree = SOURCE_ROOT; }; + B195AD6CEB9B6E3625C8D087 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PlotUtils.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp; sourceTree = SOURCE_ROOT; }; + 521FECC75E9DDB0D34B22AF8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PlotUtils.h; path = ../../Source/Processors/Visualization/SpikePlotting/PlotUtils.h; sourceTree = SOURCE_ROOT; }; + 2FA2FA826CBAD9C639A61E4A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProjectionAxes.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp; sourceTree = SOURCE_ROOT; }; + B1CF7BFC5F1892735D4FA1EE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProjectionAxes.h; path = ../../Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h; sourceTree = SOURCE_ROOT; }; + 50E7B88E8140BB293B27ED67 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SimpleKeyEvent.h; path = ../../Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h; sourceTree = SOURCE_ROOT; }; + FBB9A423728922E96F55074F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TetrodePlot.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp; sourceTree = SOURCE_ROOT; }; + 6CFF95D08DB1000B1EDD1240 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TetrodePlot.h; path = ../../Source/Processors/Visualization/SpikePlotting/TetrodePlot.h; sourceTree = SOURCE_ROOT; }; + 9F208A66C09E80D14F087CB1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WaveAxes.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp; sourceTree = SOURCE_ROOT; }; + A3F978AE6999903C47650173 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WaveAxes.h; path = ../../Source/Processors/Visualization/SpikePlotting/WaveAxes.h; sourceTree = SOURCE_ROOT; }; + E7247F5EE9588903C924994F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeObject.cpp; path = ../../Source/Processors/Visualization/SpikeObject.cpp; sourceTree = SOURCE_ROOT; }; + B0A6A0635113C4B4CD424BEC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeObject.h; path = ../../Source/Processors/Visualization/SpikeObject.h; sourceTree = SOURCE_ROOT; }; + 7A9A31FC1AE8FB238FAE995E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayCanvas.cpp; path = ../../Source/Processors/Visualization/SpikeDisplayCanvas.cpp; sourceTree = SOURCE_ROOT; }; + 9E884AEDB6035FFC74886EE8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayCanvas.h; path = ../../Source/Processors/Visualization/SpikeDisplayCanvas.h; sourceTree = SOURCE_ROOT; }; + 9ACFB6A181D09434268CE006 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Visualizer.h; path = ../../Source/Processors/Visualization/Visualizer.h; sourceTree = SOURCE_ROOT; }; ED179D5A10DD051DDB3ECB8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataWindow.cpp; path = ../../Source/Processors/Visualization/DataWindow.cpp; sourceTree = SOURCE_ROOT; }; 63C18F4066C75D3C312877D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataWindow.h; path = ../../Source/Processors/Visualization/DataWindow.h; sourceTree = SOURCE_ROOT; }; 2E96DA81EE37A0ECE471A928 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayCanvas.cpp; path = ../../Source/Processors/Visualization/LfpDisplayCanvas.cpp; sourceTree = SOURCE_ROOT; }; @@ -196,12 +259,14 @@ 7738F51AE0EC63D76EE0F761 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OpenGLCanvas.h; path = ../../Source/Processors/Visualization/OpenGLCanvas.h; sourceTree = SOURCE_ROOT; }; 3DD0741FCFBC7563EC722D9B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDetector.cpp; path = ../../Source/Processors/SpikeDetector.cpp; sourceTree = SOURCE_ROOT; }; 6E4B37AA4BFEB5A37E3AC250 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDetector.h; path = ../../Source/Processors/SpikeDetector.h; sourceTree = SOURCE_ROOT; }; - 5AC4DD48CCB1AB4936A2DE4A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FileReader.cpp; path = ../../Source/Processors/FileReader.cpp; sourceTree = SOURCE_ROOT; }; - 44E93A2D64EB5ADA54CB2CFB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileReader.h; path = ../../Source/Processors/FileReader.h; sourceTree = SOURCE_ROOT; }; B7750B27E4F3748ECCCCF69D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioNode.cpp; path = ../../Source/Processors/AudioNode.cpp; sourceTree = SOURCE_ROOT; }; 12866D44BE115E8837468F48 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioNode.h; path = ../../Source/Processors/AudioNode.h; sourceTree = SOURCE_ROOT; }; FA57CE4F63FF1592D6B3F9B5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EventNode.cpp; path = ../../Source/Processors/EventNode.cpp; sourceTree = SOURCE_ROOT; }; 32163C956C8A6F5C1DD7FE7F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EventNode.h; path = ../../Source/Processors/EventNode.h; sourceTree = SOURCE_ROOT; }; + F0B09605D4108F0F94EF3B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayEditor.cpp; path = ../../Source/Processors/Editors/SpikeDisplayEditor.cpp; sourceTree = SOURCE_ROOT; }; + 2A46D8E3EC7207D969A2B202 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayEditor.h; path = ../../Source/Processors/Editors/SpikeDisplayEditor.h; sourceTree = SOURCE_ROOT; }; + 9A3976537C96B39716B5312D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = VisualizerEditor.cpp; path = ../../Source/Processors/Editors/VisualizerEditor.cpp; sourceTree = SOURCE_ROOT; }; + C546D55EDE65ADDD95C6A6F5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VisualizerEditor.h; path = ../../Source/Processors/Editors/VisualizerEditor.h; sourceTree = SOURCE_ROOT; }; AD73EA6B24378294003DC2D0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MergerEditor.cpp; path = ../../Source/Processors/Editors/MergerEditor.cpp; sourceTree = SOURCE_ROOT; }; B7FD86B9DA02771D3519FAA0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MergerEditor.h; path = ../../Source/Processors/Editors/MergerEditor.h; sourceTree = SOURCE_ROOT; }; 544DA1EF90EBBDB6FF2DE0A5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ImageIcon.cpp; path = ../../Source/Processors/Editors/ImageIcon.cpp; sourceTree = SOURCE_ROOT; }; @@ -268,8 +333,6 @@ 1561F28CD560AB8F2E177628 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InfoLabel.h; path = ../../Source/UI/InfoLabel.h; sourceTree = SOURCE_ROOT; }; B977C2809B309C8038CB5D95 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataViewport.cpp; path = ../../Source/UI/DataViewport.cpp; sourceTree = SOURCE_ROOT; }; 877F9F9DA7A1B51D3EDCBC07 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataViewport.h; path = ../../Source/UI/DataViewport.h; sourceTree = SOURCE_ROOT; }; - 2F53BB2693AA5F1C2F27AF7C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Configuration.cpp; path = ../../Source/UI/Configuration.cpp; sourceTree = SOURCE_ROOT; }; - DE21954E89A302C554C403B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Configuration.h; path = ../../Source/UI/Configuration.h; sourceTree = SOURCE_ROOT; }; EEDA71600D817BF9444FE3E7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MessageCenter.cpp; path = ../../Source/UI/MessageCenter.cpp; sourceTree = SOURCE_ROOT; }; 4EE6CA70F229EDE04E7E320B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MessageCenter.h; path = ../../Source/UI/MessageCenter.h; sourceTree = SOURCE_ROOT; }; 5AB4A3A63B9FDEAB09EEC9C8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ControlPanel.cpp; path = ../../Source/UI/ControlPanel.cpp; sourceTree = SOURCE_ROOT; }; @@ -303,6 +366,31 @@ F8CAE2412B173788F325BD8B, 363B59958615D35C5C948300 ); name = Fonts; sourceTree = "<group>"; }; 891C5A157F059822288EDC9F = { isa = PBXGroup; children = ( + 4DB02C352236D9D030E01205, + EEAB043F90902D8F9D1102C2, + 8086EC3AFDEA802E0B43F19E, + 2171C4356B44D4CD6865E06B, + C25CAC3FC9AE387CD597DF37, + 59CAEFDE36164ABB19B3CA76, + E0587F61AD4A92C2661E5073, + 87F60F05136FEBD8A36AE670, + 1E849F999A8333FFF0B57C6D, + A5231F3D01B88C063D10026A, + 40A802FCEDFDE7B2FFEBDEA8, + 8A3AE5CF9D452810BA48A3EF, + B3CDC8825DAD5A7D75956726, + ED50AB550D058BEB30F12C7D, + 17E38F29BD6CBC490B5EF1B4, + D95C78F42494CD5995FBC15E, + 20B50BC2221C593AC67D80F8, + 771E8D912F94E52AF7E05F91, + CE771F502D1D710B28632E3A, + 05D0A12F2A850EEC48D5EDD4, + 8F8F55DD042F61BB213AFC0B, + 7C09194091360867C4CAB0E8, + 126B0DE9B8D4E42DA7D57AAB, + BDFFB5B0A8E8A022C25D7FDB, + 3D20C932FB058CC20989B129, 8E041C8C49F1A5B710CC812C, 2A1D9144C59B92B32483924B, D99F56FB46F631F67AF23F2C, @@ -378,7 +466,31 @@ 7977CAB4A151C41F4140FE1A, 9A47B52E5E1CD17DC9C72B53, B92E8189F69E0B926C73B654 ); name = Utilities; sourceTree = "<group>"; }; + 1255E9B28ADAA1A1CADC4A6E = { isa = PBXGroup; children = ( + C92B3F413B0F24752ADE6730, + FDD549F527C378CF36BDB8C7, + 3BB44F767E701E3642435FA0, + 1AAF672654B16469EFB41AC2, + 41591F74A761BAC908FA8AD8, + 9C8EA29582DBFF6E5A14B8A3, + 24C6D768C87E1C42C644C4BD, + BCBB865ED53E8AFD278D1A53, + B195AD6CEB9B6E3625C8D087, + 521FECC75E9DDB0D34B22AF8, + 2FA2FA826CBAD9C639A61E4A, + B1CF7BFC5F1892735D4FA1EE, + 50E7B88E8140BB293B27ED67, + FBB9A423728922E96F55074F, + 6CFF95D08DB1000B1EDD1240, + 9F208A66C09E80D14F087CB1, + A3F978AE6999903C47650173 ); name = SpikePlotting; sourceTree = "<group>"; }; 15543D7982B26B70879960F4 = { isa = PBXGroup; children = ( + 1255E9B28ADAA1A1CADC4A6E, + E7247F5EE9588903C924994F, + B0A6A0635113C4B4CD424BEC, + 7A9A31FC1AE8FB238FAE995E, + 9E884AEDB6035FFC74886EE8, + 9ACFB6A181D09434268CE006, ED179D5A10DD051DDB3ECB8B, 63C18F4066C75D3C312877D8, 2E96DA81EE37A0ECE471A928, @@ -386,6 +498,10 @@ 0C5335B0E57C9DC92FC57E5F, 7738F51AE0EC63D76EE0F761 ); name = Visualization; sourceTree = "<group>"; }; 953CC35B9116404D6AA8D1C7 = { isa = PBXGroup; children = ( + F0B09605D4108F0F94EF3B57, + 2A46D8E3EC7207D969A2B202, + 9A3976537C96B39716B5312D, + C546D55EDE65ADDD95C6A6F5, AD73EA6B24378294003DC2D0, B7FD86B9DA02771D3519FAA0, 544DA1EF90EBBDB6FF2DE0A5, @@ -426,6 +542,10 @@ 72123888A7DD78159AA032AF, 2164BFCDF57A5AA752CAA3A2 ); name = DataThreads; sourceTree = "<group>"; }; 33A88A7C3FF426F051834D6A = { isa = PBXGroup; children = ( + 751C52F2BEA7F1328ED13333, + 7B825983F25D8984E02F6FFB, + 4AEDD076CCA918481C6F9CF2, + 671CC5EA3DF4F21E9A7E392B, 268005410FB62BCB9099A762, 32959675287F77DD9B7FA96B, 5935F823A2EE45AC36A0201F, @@ -434,8 +554,6 @@ 15543D7982B26B70879960F4, 3DD0741FCFBC7563EC722D9B, 6E4B37AA4BFEB5A37E3AC250, - 5AC4DD48CCB1AB4936A2DE4A, - 44E93A2D64EB5ADA54CB2CFB, B7750B27E4F3748ECCCCF69D, 12866D44BE115E8837468F48, FA57CE4F63FF1592D6B3F9B5, @@ -471,8 +589,6 @@ 1561F28CD560AB8F2E177628, B977C2809B309C8038CB5D95, 877F9F9DA7A1B51D3EDCBC07, - 2F53BB2693AA5F1C2F27AF7C, - DE21954E89A302C554C403B3, EEDA71600D817BF9444FE3E7, 4EE6CA70F229EDE04E7E320B, 5AB4A3A63B9FDEAB09EEC9C8, @@ -539,6 +655,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "_DEBUG=1", "DEBUG=1", + "JUCE_ObjCExtraSuffix=fea2mT", "JUCER_XCODE_MAC_F6D2F4CF=1"); }; name = Debug; }; 5D7484BAF16E272FF0E9EEAE = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; @@ -554,6 +671,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "_NDEBUG=1", "NDEBUG=1", + "JUCE_ObjCExtraSuffix=fea2mT", "JUCER_XCODE_MAC_F6D2F4CF=1"); }; name = Release; }; 4E274274B609972E0988736B = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -613,17 +731,30 @@ 8E138283FC265B58D252AAC3, EE1DC0B09AE0727BC7A5A99C, 4ACF816CB5CDB285D8005AB8, + 717D108DC8B2379D556C4B2F, + 1F67A9ACD509FB4DC5A633DF, B992DDBFF8928A985EEE1557, F1268EC5E783EC8ECEBCA5D3, 4A00153E1E69A74BC6B7D8A6, 5F13B8FFB1584BFF6C05AD39, + B11D72764B1B17BF2B8C6E67, + 938FC2F779C2CF4B8C7ECFFE, + 55A240CCFCD604CA8DF8FC8C, + 8025F04ED261C7F7D2DC0F06, + 49F046C8BE137BF77338DD7B, + 566E42D2B7105CFB4DB45170, + 0DDC562EC2B04A26AE6CBB2B, + BCD7C4797178C8EF65CDC2D7, + 9145D84C7D665BCAFE698432, + 7659F31912D12C91E9554909, 9D687F73F2FD2462C5D5588C, B13883377C9316B9603336B4, 073B178E7EF1759BA0AACCCE, 4BE0DDA01B73223EF0BD934A, - 6656467170D2822949BD2F7F, 08B501E0D7764C6B613AF529, 9CBA3837CC8CAA03A03F2D9C, + DD22A06702F4CF995893DD5C, + F4CEF74DDCD7EFA0891249B5, 93A3E6284F2DAED3F491332B, CB77C89226102EF30F85E3EC, A126280FF39A61DEFD3ABFE5, @@ -657,7 +788,6 @@ 13457B3248E7646270A4FF88, D060C0893EDAE6CBC86A5FE2, E36C0018635A85E09D4EDE01, - 4BE24CDF92926150BFC83ED2, C170A763D33146C74ED4CE4B, 116BB2F62451986C75586F9D, 1F301384375DA0F3652C01DA, diff --git a/JuceLibraryCode/BinaryData.cpp b/JuceLibraryCode/BinaryData.cpp index ab8f390247024fdd51802cc565d95c86cac9ee03..6eaabf40614aa2688907e6aa1286a24d10474141 100644 --- a/JuceLibraryCode/BinaryData.cpp +++ b/JuceLibraryCode/BinaryData.cpp @@ -30,6 +30,31 @@ const char* BinaryData::getNamedResource (const char* resourceNameUTF8, int& num case 0x1eb42b13: numBytes = BinaryData::ostrich_ttfSize; return BinaryData::ostrich_ttf; case 0xafad3345: numBytes = BinaryData::silkscreenserializedSize; return BinaryData::silkscreenserialized; case 0xac0c53a8: numBytes = BinaryData::silkscreen_ttfSize; return BinaryData::silkscreen_ttf; + case 0x9dbdc191: numBytes = BinaryData::RadioButtons01_pngSize; return BinaryData::RadioButtons01_png; + case 0x9dcbd912: numBytes = BinaryData::RadioButtons02_pngSize; return BinaryData::RadioButtons02_png; + case 0x9dd9f093: numBytes = BinaryData::RadioButtons03_pngSize; return BinaryData::RadioButtons03_png; + case 0x9de80814: numBytes = BinaryData::RadioButtons04_pngSize; return BinaryData::RadioButtons04_png; + case 0x9df61f95: numBytes = BinaryData::RadioButtons05_pngSize; return BinaryData::RadioButtons05_png; + case 0xa1a5fa19: numBytes = BinaryData::RadioButtons_neutral01_pngSize; return BinaryData::RadioButtons_neutral01_png; + case 0xa1b4119a: numBytes = BinaryData::RadioButtons_neutral02_pngSize; return BinaryData::RadioButtons_neutral02_png; + case 0xa1c2291b: numBytes = BinaryData::RadioButtons_neutral03_pngSize; return BinaryData::RadioButtons_neutral03_png; + case 0xa1d0409c: numBytes = BinaryData::RadioButtons_neutral04_pngSize; return BinaryData::RadioButtons_neutral04_png; + case 0xa1de581d: numBytes = BinaryData::RadioButtons_neutral05_pngSize; return BinaryData::RadioButtons_neutral05_png; + case 0x91e6977f: numBytes = BinaryData::RadioButtons_selected01_pngSize; return BinaryData::RadioButtons_selected01_png; + case 0x91f4af00: numBytes = BinaryData::RadioButtons_selected02_pngSize; return BinaryData::RadioButtons_selected02_png; + case 0x9202c681: numBytes = BinaryData::RadioButtons_selected03_pngSize; return BinaryData::RadioButtons_selected03_png; + case 0x9210de02: numBytes = BinaryData::RadioButtons_selected04_pngSize; return BinaryData::RadioButtons_selected04_png; + case 0x921ef583: numBytes = BinaryData::RadioButtons_selected05_pngSize; return BinaryData::RadioButtons_selected05_png; + case 0x0634464a: numBytes = BinaryData::RadioButtons_selected_over01_pngSize; return BinaryData::RadioButtons_selected_over01_png; + case 0x06425dcb: numBytes = BinaryData::RadioButtons_selected_over02_pngSize; return BinaryData::RadioButtons_selected_over02_png; + case 0x0650754c: numBytes = BinaryData::RadioButtons_selected_over03_pngSize; return BinaryData::RadioButtons_selected_over03_png; + case 0x065e8ccd: numBytes = BinaryData::RadioButtons_selected_over04_pngSize; return BinaryData::RadioButtons_selected_over04_png; + case 0x066ca44e: numBytes = BinaryData::RadioButtons_selected_over05_pngSize; return BinaryData::RadioButtons_selected_over05_png; + case 0x0d14b768: numBytes = BinaryData::noise_wave_pngSize; return BinaryData::noise_wave_png; + case 0x96fe1b79: numBytes = BinaryData::saw_wave_pngSize; return BinaryData::saw_wave_png; + case 0xd15cb155: numBytes = BinaryData::sine_wave_pngSize; return BinaryData::sine_wave_png; + case 0xd4df18c5: numBytes = BinaryData::square_wave_pngSize; return BinaryData::square_wave_png; + case 0x5f96403a: numBytes = BinaryData::triangle_wave_pngSize; return BinaryData::triangle_wave_png; case 0xb01cfdff: numBytes = BinaryData::wifi_pngSize; return BinaryData::wifi_png; case 0x593e4e34: numBytes = BinaryData::SourceDrop_pngSize; return BinaryData::SourceDrop_png; case 0x6189efd0: numBytes = BinaryData::DefaultDataSource_pngSize; return BinaryData::DefaultDataSource_png; @@ -5840,6 +5865,1122 @@ static const unsigned char temp_46c3ac32[] = const char* BinaryData::silkscreen_ttf = (const char*) temp_46c3ac32; +//================== RadioButtons-01.png ================== +static const unsigned char temp_819db025[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,19,8,6,0,0,0,241,148,15,247,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,191,73,68,65,84,120,218,196,150,219,78,19,81,20,134,255,61,199,118,128,136,209,132,150,27,98,226,133,70,99,104,69,206,82,18,9,166,49,122,161,9,23,92,250,4,190,129,190,130,207,161,55,106,76,19,37,86,40,162,40,109,154,84,4, +34,98,5,76,228,2,16,122,156,233,28,92,211,169,74,109,109,13,69,88,201,206,236,116,239,174,245,173,127,173,189,103,24,200,60,30,207,29,122,4,104,180,226,144,141,81,240,123,62,255,197,187,221,221,189,80,20,229,80,131,71,34,83,16,36,73,12,140,94,13,226, +40,140,231,121,2,16,37,72,146,84,95,42,246,123,110,89,7,4,32,16,128,61,17,69,177,230,70,142,3,100,201,66,65,203,17,9,7,11,46,24,198,1,0,112,255,0,96,103,238,146,13,180,52,73,232,31,188,133,141,141,175,136,206,69,96,152,10,13,214,16,0,199,115,14,128,93, +139,90,193,155,20,25,125,253,65,168,185,37,120,218,78,163,171,235,50,98,177,25,240,86,99,16,28,171,1,192,24,9,45,25,112,187,5,244,246,5,241,125,251,3,22,23,150,209,222,190,137,142,83,61,240,251,251,17,143,191,166,255,54,215,129,176,27,134,253,37,65,6, +238,231,100,239,224,56,70,153,91,112,187,248,82,240,5,36,18,73,236,102,100,44,175,236,32,185,242,22,109,30,15,58,59,251,32,112,25,8,66,117,31,50,249,216,218,92,135,88,101,221,30,54,151,160,21,52,164,82,169,138,236,185,22,29,129,192,24,54,190,197,16,141, +126,68,54,207,195,52,89,177,44,246,254,108,46,131,51,103,135,112,238,124,55,102,103,195,208,237,158,48,88,73,90,144,114,164,158,44,99,124,252,54,66,161,135,180,159,175,56,61,154,170,17,128,86,160,12,183,43,106,159,207,89,152,142,60,192,218,250,14,114, +57,142,130,151,175,239,238,238,144,131,28,206,95,24,133,207,55,128,201,201,16,52,221,85,220,167,184,45,52,43,77,24,24,188,137,181,213,69,108,109,145,143,60,115,170,177,199,242,249,188,211,3,170,166,149,3,216,116,244,211,251,249,205,34,181,89,229,220, +219,235,115,177,85,20,244,16,124,254,32,134,2,65,132,95,60,129,36,139,56,222,122,12,35,163,99,88,95,91,196,84,100,18,233,52,163,62,169,244,97,24,186,3,160,105,234,190,186,216,134,120,55,151,36,71,79,209,117,233,26,174,140,92,199,202,167,104,49,243,213, +47,11,8,135,39,144,74,163,106,112,7,192,40,1,168,218,190,143,146,74,236,111,102,151,201,217,99,244,244,222,128,215,219,129,228,231,121,60,159,120,70,101,50,203,74,247,167,233,122,9,64,85,213,134,46,20,91,192,87,51,75,228,231,17,78,156,108,163,204,167, +139,193,13,163,246,157,221,112,9,202,148,32,17,195,47,19,116,2,18,208,41,176,105,214,127,97,252,42,65,58,157,174,251,62,248,31,166,235,142,2,247,227,241,216,176,215,219,78,23,198,225,66,100,179,25,231,142,164,143,146,97,122,12,31,197,55,193,15,1,6,0, +156,20,41,102,255,70,71,224,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons01_png = (const char*) temp_819db025; + +//================== RadioButtons-02.png ================== +static const unsigned char temp_81abc7a6[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,197,73,68,65,84,120,218,196,150,107,79,19,65,20,134,223,153,157,221,110,11,36,152,20,104,52,154,144,160,40,69,32,164,40,136,52,38,24,141,31,252,79,254,31,191,154,104,248,224,133,86,80,145,134,91,32,70,32,202,69,46,134,91, +111,123,233,94,60,179,106,44,180,24,109,19,152,228,100,119,178,115,206,115,230,61,115,38,203,98,177,216,43,156,211,16,137,129,219,247,70,70,146,103,14,78,165,198,33,20,69,129,22,10,157,57,92,114,133,34,8,174,105,167,46,98,140,228,81,200,132,15,159,230, +142,195,224,186,128,239,215,9,23,18,206,21,168,170,90,117,1,231,64,88,247,160,48,7,109,177,203,1,112,107,107,29,158,175,194,178,24,61,235,128,19,87,112,133,87,133,203,29,71,116,23,225,176,138,129,91,143,41,75,27,114,239,93,241,4,222,77,142,145,18,30, +44,155,215,172,128,228,10,206,120,160,255,73,176,166,122,208,67,14,129,31,193,182,246,144,89,152,38,37,124,196,227,253,24,28,122,128,247,147,47,104,29,67,201,169,45,1,201,229,50,128,132,151,155,170,50,52,70,28,116,223,76,194,117,242,152,155,159,197,81, +86,197,225,145,134,197,197,25,42,184,129,158,190,36,84,97,144,85,250,7,49,4,71,72,99,193,83,81,120,197,119,201,229,96,8,94,126,27,231,140,156,128,150,214,43,104,104,108,194,234,234,34,10,69,218,29,45,245,124,142,108,78,96,109,109,1,145,136,142,142,171, +125,36,191,9,41,92,121,12,57,215,84,3,26,149,70,85,157,32,102,249,119,105,146,43,108,203,70,46,151,251,35,57,153,29,114,113,189,179,3,43,203,25,124,94,222,14,164,45,47,137,97,100,41,65,29,209,214,46,124,219,92,193,238,247,44,29,64,30,116,67,112,86,194, +46,218,90,162,184,214,57,136,185,217,183,216,216,60,162,196,217,49,217,37,87,152,166,137,195,131,131,227,53,39,214,243,23,175,3,7,217,86,240,43,187,96,218,153,193,221,225,102,196,187,135,177,251,242,41,242,121,15,14,173,13,105,62,26,116,142,139,151,146, +20,247,43,37,255,5,134,201,42,98,72,46,119,93,135,78,173,125,204,76,211,70,161,80,130,81,164,185,101,87,253,190,179,99,33,147,73,195,243,12,36,18,163,84,219,28,129,45,232,90,30,157,55,134,232,176,114,140,167,222,144,170,165,170,49,36,87,184,180,53,219, +182,254,251,180,146,63,237,202,70,83,83,10,61,189,163,24,186,243,16,235,107,75,104,111,239,69,52,218,138,137,137,49,74,208,248,121,33,85,241,151,92,225,144,86,82,255,90,134,76,224,195,212,10,221,122,62,250,251,7,17,107,187,79,109,87,64,58,253,12,243, +11,27,40,149,78,239,65,201,21,129,236,150,85,243,77,37,93,83,233,37,76,125,252,132,11,205,13,216,219,207,83,89,124,42,135,255,215,254,175,75,246,147,9,20,10,192,254,126,241,159,47,156,95,178,215,183,243,90,135,228,138,98,177,128,157,237,237,51,135,75, +46,163,63,153,39,231,245,39,243,67,128,1,0,60,21,103,165,70,150,193,96,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons02_png = (const char*) temp_81abc7a6; + +//================== RadioButtons-03.png ================== +static const unsigned char temp_81b9df27[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,77,73,68,65,84,120,218,196,150,219,110,211,64,16,134,255,61,196,109,66,165,86,106,47,242,32,173,8,23,69,240,16,136,103,225,142,151,42,92,34,40,32,113,1,151,160,34,78,82,213,67,148,66,147,56,118,236,181,119,205,76,156,162, +172,157,22,25,161,116,164,141,226,221,153,249,230,228,149,69,183,219,125,129,91,18,189,187,119,247,193,254,254,253,149,131,15,15,95,65,43,165,16,172,173,173,28,206,92,173,52,193,131,160,118,40,37,32,4,45,126,16,75,172,11,192,209,42,230,171,49,92,51,92, +42,180,90,45,191,23,138,157,199,232,116,52,148,20,75,141,25,24,197,6,66,118,144,229,162,113,0,204,213,82,201,26,188,189,110,177,183,251,16,119,54,118,254,234,228,205,235,103,8,35,221,24,206,92,45,133,156,213,255,74,184,212,65,80,204,202,62,141,142,48, +24,28,35,207,53,10,47,106,135,173,205,54,182,182,239,145,46,217,39,170,57,156,184,90,16,109,17,206,205,84,76,38,137,99,129,147,83,32,49,133,215,120,10,154,180,4,193,121,54,216,94,18,252,154,193,192,242,161,97,174,230,125,254,179,184,41,68,57,109,12,160, +26,144,99,89,141,123,190,174,244,69,13,160,100,129,233,52,36,219,2,235,237,205,122,112,244,168,77,106,16,134,161,183,159,25,11,147,230,148,185,193,104,60,129,49,178,50,144,236,24,176,214,34,138,38,100,223,170,57,231,185,233,245,122,24,94,254,196,199, +79,95,104,40,125,31,204,213,73,146,144,194,165,119,16,82,23,222,127,120,139,148,2,184,184,72,224,92,229,102,210,212,146,72,206,224,163,209,24,195,33,245,220,249,89,185,13,71,231,41,178,44,198,120,60,36,95,126,112,204,213,214,230,72,141,169,86,4,95,191, +253,250,211,182,234,44,113,48,57,129,89,172,205,8,96,61,56,119,33,207,139,89,201,29,41,27,242,111,140,240,252,48,87,115,244,198,164,141,38,181,112,130,156,151,240,73,120,138,120,82,94,56,139,193,43,250,177,185,33,8,195,51,74,208,79,129,185,154,157,112, +253,155,136,179,130,202,88,194,31,61,126,114,163,110,191,63,32,93,202,60,245,225,204,45,203,158,54,203,60,163,88,191,255,56,193,206,246,75,186,44,236,245,21,162,183,228,232,243,49,205,71,74,109,170,102,254,143,101,103,57,59,51,56,120,254,14,66,220,208, +30,190,255,169,31,214,214,111,160,121,217,155,103,254,63,132,185,58,142,35,244,207,207,87,14,103,174,160,47,153,167,183,245,37,243,91,128,1,0,11,149,65,182,96,70,58,8,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons03_png = (const char*) temp_81b9df27; + +//================== RadioButtons-04.png ================== +static const unsigned char temp_81c7f6a8[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,165,73,68,65,84,120,218,196,150,237,79,211,80,24,197,207,109,111,1,157,74,50,144,76,226,198,139,128,2,66,162,66,136,31,48,42,248,217,232,95,228,127,102,2,74,130,38,203,192,12,84,134,1,231,88,145,142,194,218,117,107,215,23, +159,219,161,216,161,198,200,132,155,52,109,239,189,233,239,60,231,60,109,202,18,137,196,75,156,211,224,83,211,51,15,103,103,31,156,57,120,113,113,1,92,150,101,180,181,183,159,57,92,112,185,204,9,222,214,118,98,145,177,227,235,32,248,15,112,46,224,146, +12,69,81,34,11,146,36,136,85,48,248,225,38,63,104,135,231,177,150,138,16,92,46,201,210,9,184,194,3,140,143,77,226,90,239,8,242,159,115,216,204,101,225,250,194,129,14,120,126,107,68,8,46,151,152,20,250,31,129,43,62,56,23,213,87,208,215,215,133,100,234, +41,242,249,28,212,226,22,42,149,42,249,113,225,212,78,8,46,103,20,110,20,30,144,170,70,230,182,109,33,191,253,22,241,174,36,82,201,1,36,147,67,216,223,223,195,198,135,12,12,211,160,70,237,60,18,193,126,131,248,174,142,253,162,167,24,184,152,103,63,119, +23,77,72,172,113,246,3,9,135,134,2,117,79,67,236,162,134,84,170,7,221,221,253,136,223,127,18,138,200,109,172,192,52,77,106,216,78,184,158,20,113,130,177,128,114,245,96,24,101,196,46,197,225,251,77,2,232,150,59,182,67,27,140,200,124,141,251,176,44,135, +236,119,161,235,22,172,154,140,125,29,40,170,155,136,197,54,209,155,136,99,96,112,16,247,166,30,133,34,62,190,79,195,52,74,20,85,39,234,110,195,9,17,221,237,177,27,184,114,101,2,203,111,150,81,179,165,8,67,112,121,173,86,195,129,174,71,69,209,190,108, +118,13,29,29,28,234,87,19,158,123,188,166,149,128,66,225,0,107,235,57,140,12,95,37,17,19,152,158,153,135,166,237,98,117,101,9,229,67,141,98,188,12,145,164,235,90,116,56,36,76,135,105,73,199,41,136,2,137,203,61,122,178,237,56,205,142,224,203,142,243,35, +182,230,190,18,235,150,5,232,7,69,188,203,22,49,122,179,7,195,195,119,240,120,238,89,40,98,37,243,26,229,178,74,241,121,228,66,0,167,94,167,74,89,228,57,130,75,112,15,142,99,255,83,199,50,187,33,98,73,47,32,179,90,32,155,123,113,107,244,46,230,230,159, +83,92,187,240,93,35,132,215,5,220,9,154,224,30,184,235,122,161,255,167,29,66,196,171,165,45,164,51,219,152,156,184,142,241,241,41,112,101,8,165,210,14,89,236,208,155,19,245,79,112,27,182,219,118,203,190,92,66,196,194,98,14,233,244,39,18,208,143,106,213, +167,134,182,195,202,209,74,219,255,52,42,21,134,61,109,61,188,246,253,224,196,7,233,200,246,214,86,254,183,67,112,185,101,85,176,171,170,103,14,23,92,70,127,50,47,206,235,79,230,155,0,3,0,91,7,91,249,23,102,61,167,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons04_png = (const char*) temp_81c7f6a8; + +//================== RadioButtons-05.png ================== +static const unsigned char temp_81d60e29[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,30,0,0,0,19,8,6,0,0,0,135,174,189,124,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,3,59,73,68,65,84,120,218,188,86,91,79,19,81,16,254,118,247,244,94,160,208,2,229,98,137,37,38,154,0,33,154,24,34,193,152,24,227,139,202,139,62,250,95,252,9,254,4,159,140,190,171,49,74,226,237,197,68,154,24,64,5,74,145,164,152, +110,239,133,182,219,221,109,119,143,179,91,16,106,91,245,197,78,114,218,115,153,51,223,204,55,51,39,43,132,195,225,55,232,173,188,163,241,80,184,117,123,153,47,45,93,237,9,98,189,94,71,124,123,11,43,43,175,222,50,73,146,224,116,185,122,2,108,225,204, +95,188,132,120,124,251,26,147,24,1,59,157,61,229,218,194,99,146,40,193,225,112,116,84,16,126,253,0,156,211,84,56,25,220,4,76,222,217,176,72,231,18,163,67,46,160,97,52,239,182,216,37,3,76,148,196,142,192,22,30,163,203,165,98,6,67,193,97,202,143,8,65,228, +112,59,57,25,117,216,249,82,53,177,197,232,177,163,46,167,137,177,240,56,10,133,20,84,157,67,215,91,245,68,242,140,134,8,43,207,191,15,230,144,48,48,224,194,221,123,247,225,247,74,240,249,0,159,23,56,127,97,14,139,139,215,17,232,23,225,113,11,228,52, +49,70,233,114,187,68,168,106,158,64,53,58,19,108,189,43,139,55,225,243,88,1,180,218,182,188,99,86,216,205,197,105,225,100,140,35,20,28,180,87,151,23,110,224,203,250,123,24,134,134,145,145,113,123,47,20,26,163,98,49,160,84,51,200,229,11,232,247,135,176, +176,176,140,124,46,5,203,156,32,24,40,230,215,97,152,140,162,19,109,122,79,168,38,103,32,160,101,243,56,71,162,160,193,235,237,131,217,72,219,30,134,134,135,80,215,203,77,183,12,25,147,145,89,123,190,27,127,137,153,185,59,112,187,189,246,122,242,204, +180,253,175,214,210,72,236,102,161,215,29,246,253,86,8,138,88,215,116,148,203,229,22,96,137,114,57,59,19,37,176,41,202,241,6,28,78,31,81,29,68,78,41,80,212,6,106,213,36,60,190,97,91,119,100,244,44,209,237,178,247,85,101,13,30,111,132,248,10,160,88,76, +35,95,80,80,83,165,182,250,209,52,21,76,85,85,50,94,108,45,44,17,88,91,255,76,148,113,236,39,119,48,26,142,160,175,143,195,229,98,208,181,44,209,171,192,233,54,142,10,165,223,6,229,166,130,88,44,134,200,84,29,227,19,243,56,40,89,192,7,164,47,180,1,215, +8,147,25,70,3,154,174,183,85,116,154,24,126,189,242,145,10,3,8,12,78,96,98,114,10,133,92,6,181,154,138,108,54,143,64,176,169,203,156,65,210,47,82,158,127,32,69,119,220,158,28,1,3,197,82,133,116,235,104,52,218,219,141,83,31,50,203,91,93,215,186,246,177, +36,9,144,229,20,162,148,58,159,127,26,135,135,50,69,82,194,185,83,122,187,137,13,124,90,221,66,165,74,185,99,57,68,163,73,236,36,168,149,106,157,123,221,52,77,176,6,117,184,149,231,110,66,5,73,212,52,221,246,122,253,72,36,178,216,221,171,80,110,99,212, +94,2,229,116,0,95,191,125,71,161,168,19,229,192,254,190,134,39,79,159,209,156,219,235,78,98,210,235,211,164,90,211,186,2,91,213,184,185,185,71,252,60,70,165,162,64,78,43,212,175,38,158,191,248,64,207,94,179,90,245,58,39,74,121,219,11,213,77,254,74,245, +73,21,2,171,177,228,209,211,249,239,0,221,228,136,234,63,71,252,63,68,167,98,102,138,82,69,90,150,123,6,154,205,102,168,64,15,30,10,244,5,242,160,199,95,32,123,178,44,63,250,41,192,0,169,115,113,154,200,139,135,81,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons05_png = (const char*) temp_81d60e29; + +//================== RadioButtons_neutral-01.png ================== +static const unsigned char temp_38c869d[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,19,8,6,0,0,0,241,148,15,247,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,103,73,68,65,84,120,218,196,86,221,75,83,97,28,126,206,217,217,161,177,205,64,177,121,154,125,96,132,23,125,144,36,117,219,77,222,108,115,36,74,11,22,140,210,182,187,162,174,130,46,250,83,6,121,83,162,99,69,69,17,164,77,152, +168,67,48,203,106,141,105,160,172,109,110,147,181,185,243,181,211,123,142,37,68,251,10,199,250,193,15,94,206,251,62,239,243,252,62,248,157,151,82,20,5,28,199,221,49,27,141,55,201,218,140,22,27,67,200,31,234,245,250,251,54,199,32,123,200,194,181,148,252, +237,155,215,96,218,76,38,183,243,202,16,107,225,172,173,14,30,58,157,14,140,193,96,96,143,30,239,193,255,48,154,166,193,80,20,64,74,208,16,96,61,246,5,166,182,131,232,232,180,52,79,0,64,129,101,217,186,135,11,219,25,220,190,123,15,185,108,22,193,224, +83,116,90,186,154,34,128,86,51,160,214,162,150,23,182,179,24,113,93,131,192,151,208,222,209,14,167,115,16,153,116,178,46,174,158,83,132,156,254,221,12,213,60,159,77,19,114,23,137,60,131,119,179,97,68,163,49,77,132,221,110,71,58,153,104,134,0,74,91,84, +242,92,250,59,134,175,238,146,71,150,150,181,111,107,235,223,16,139,197,53,17,54,155,13,201,196,102,85,188,234,95,63,175,214,216,39,115,64,148,68,165,88,44,86,172,209,208,240,8,82,201,36,230,230,23,255,248,190,242,225,35,120,158,71,111,239,73,92,30,24, +64,96,106,10,156,245,200,95,248,76,42,129,91,94,47,158,191,124,85,241,126,89,146,193,72,162,164,168,141,85,113,80,204,132,176,185,177,81,113,111,97,97,17,165,210,14,206,156,62,5,135,195,129,241,241,71,232,226,186,247,246,243,185,45,140,122,125,72,146, +0,170,221,207,139,2,24,117,20,11,130,80,241,192,90,60,94,179,139,35,145,37,72,36,138,190,115,103,225,118,95,135,223,239,135,58,77,249,66,30,163,62,31,182,210,105,188,168,18,189,106,101,185,188,43,128,175,34,160,17,155,39,153,144,101,25,253,231,251,224, +241,120,16,12,4,246,200,3,193,103,53,177,114,153,148,64,33,11,129,212,115,63,22,14,207,105,34,46,94,232,199,141,177,49,66,158,194,227,39,147,117,113,90,6,160,102,96,159,2,84,11,133,102,33,17,17,221,214,195,152,152,152,108,8,83,214,50,160,245,0,223,148, +209,58,51,61,253,79,231,101,53,3,162,36,255,136,126,90,197,177,158,19,45,255,25,169,101,99,120,129,127,176,188,242,62,176,83,42,193,108,110,237,123,68,18,69,80,191,94,68,151,140,6,131,75,71,211,7,90,157,133,159,2,12,0,238,13,9,71,19,58,158,165,0,0,0, +0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_neutral01_png = (const char*) temp_38c869d; + +//================== RadioButtons_neutral-02.png ================== +static const unsigned char temp_39a9e1e[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,54,73,68,65,84,120,218,196,150,207,79,19,65,20,199,191,187,157,182,86,131,166,254,72,69,19,13,141,137,49,30,12,218,131,225,102,106,140,129,112,52,210,150,67,19,53,130,240,223,104,188,123,210,196,171,98,148,6,127,20,104,145, +32,28,48,129,130,201,66,65,91,160,148,110,161,178,219,157,226,204,28,56,176,187,13,182,164,125,201,203,190,153,247,94,62,243,230,205,76,86,186,226,247,43,104,146,144,182,54,255,229,59,119,239,53,28,252,57,246,9,196,225,112,192,229,118,55,28,206,185,68, +150,101,184,155,0,231,92,1,119,58,157,85,3,179,171,203,8,4,2,32,44,46,153,72,192,119,241,210,209,193,93,46,151,109,208,78,97,19,79,159,13,128,16,34,198,55,218,111,226,237,155,215,56,113,234,116,221,112,89,146,36,177,255,86,186,246,103,5,15,122,66,160, +70,25,195,177,17,161,220,230,115,91,185,117,219,188,195,40,231,218,194,119,138,42,194,145,8,246,246,42,24,29,159,0,165,84,40,183,101,9,120,24,10,97,99,45,83,47,28,194,56,168,215,175,93,197,49,143,7,179,179,63,97,24,198,254,60,183,231,231,23,216,57,33, +8,6,131,216,253,91,178,204,231,243,217,223,105,108,171,5,75,63,231,18,106,80,148,74,37,83,79,206,250,124,72,205,165,160,44,165,77,190,185,212,2,60,199,61,184,208,218,10,67,219,5,195,155,123,90,161,8,133,35,152,248,62,137,141,220,166,201,207,185,68,43, +235,216,202,231,77,206,161,161,143,85,15,204,216,120,18,93,157,247,209,217,221,141,151,47,158,227,204,185,243,251,190,220,122,6,253,3,131,40,168,42,22,23,127,89,230,115,46,91,96,5,186,174,255,183,110,23,139,248,22,31,19,125,123,244,248,9,86,210,75,98, +158,127,35,189,189,172,175,50,222,189,255,96,155,207,185,132,178,237,209,216,160,22,81,20,5,83,63,166,17,184,213,142,104,52,138,145,216,48,250,250,251,112,178,165,69,236,76,145,45,208,78,56,151,136,202,53,173,230,251,154,72,36,197,45,232,232,184,141, +158,112,24,14,246,30,124,249,26,199,204,244,76,213,60,81,121,133,87,94,7,156,75,60,62,42,212,235,245,34,111,113,126,44,225,188,114,42,122,174,29,201,123,157,205,102,14,29,75,69,207,217,150,233,53,246,188,30,225,92,98,148,203,88,77,47,55,28,206,185,68, +85,11,175,152,54,229,79,230,159,0,3,0,178,38,58,166,235,164,14,20,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_neutral02_png = (const char*) temp_39a9e1e; + +//================== RadioButtons_neutral-03.png ================== +static const unsigned char temp_3a8b59f[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,1,165,73,68,65,84,120,218,196,150,109,75,194,80,20,199,207,220,221,172,12,21,122,130,40,76,139,94,7,245,162,122,19,73,244,213,194,143,209,75,251,0,69,169,212,103,136,232,77,132,154,104,69,234,210,72,216,195,189,235,222,13,133, +218,217,70,19,244,63,198,6,255,115,206,111,231,222,187,187,73,91,185,92,13,166,36,146,205,230,50,199,39,167,19,7,223,150,111,128,200,178,12,106,60,62,113,184,224,146,88,44,6,241,41,192,5,215,129,43,138,226,49,91,141,58,88,166,25,88,192,182,25,100,54, +183,199,131,171,170,234,49,15,15,246,97,103,119,47,180,200,229,213,117,116,184,36,73,206,248,99,186,171,148,33,189,176,140,122,189,110,27,142,242,121,223,220,48,9,110,32,156,49,6,237,78,7,247,12,125,180,112,198,128,187,55,136,235,156,168,55,244,1,252, +125,174,247,215,38,36,83,105,152,157,75,160,233,132,90,20,6,131,129,199,76,37,102,64,85,84,208,190,190,241,206,77,29,24,197,115,135,90,89,90,228,35,215,5,27,188,15,40,184,68,55,13,248,212,52,143,105,89,22,24,134,1,134,174,227,239,41,48,176,56,28,203, +29,53,176,190,10,50,95,88,88,140,224,18,70,153,3,249,171,174,207,92,15,165,18,183,27,44,247,215,235,200,15,44,70,112,9,101,20,244,144,2,104,231,146,187,55,60,62,220,251,198,108,100,214,248,94,96,163,245,5,215,237,220,103,104,131,148,78,206,59,215,179, +66,33,48,174,82,42,65,235,237,3,239,156,137,206,35,192,219,29,13,170,181,122,104,220,211,115,21,173,47,184,132,58,115,254,127,184,200,185,40,22,35,239,237,212,153,115,190,98,141,8,115,62,174,4,151,136,143,71,179,241,50,113,184,224,146,126,191,119,206, +207,169,252,201,252,8,48,0,227,76,197,247,89,122,10,69,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_neutral03_png = (const char*) temp_3a8b59f; + +//================== RadioButtons_neutral-04.png ================== +static const unsigned char temp_3b6cd20[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,27,73,68,65,84,120,218,196,150,109,79,211,80,24,134,239,182,167,29,219,50,100,176,110,200,48,203,22,127,5,209,15,4,162,63,68,72,36,209,175,26,241,215,248,7,28,159,36,129,69,92,228,69,167,113,250,9,156,16,141,14,98,125,9,91, +11,117,93,123,138,61,167,209,4,219,17,18,203,246,36,39,79,211,59,231,190,158,231,188,52,21,174,150,74,159,48,160,32,197,98,169,48,61,123,163,239,224,181,202,10,136,36,73,80,98,177,190,195,25,151,136,162,136,216,0,224,140,203,225,178,44,7,196,159,223, +53,28,233,109,100,39,38,17,143,39,46,14,174,40,74,64,44,92,153,196,236,205,57,108,174,63,71,253,77,29,227,121,175,136,68,50,90,184,32,8,124,253,3,162,224,162,217,108,34,63,145,199,212,181,235,188,136,247,59,59,72,103,178,145,20,193,184,61,225,112,93, +252,208,190,162,125,220,129,40,43,127,139,248,184,183,135,202,234,10,134,71,70,49,166,102,255,23,238,63,132,168,124,56,142,131,198,135,93,126,46,36,37,230,173,136,128,249,219,11,126,17,149,85,140,164,199,48,154,81,67,1,191,204,99,232,237,22,114,151,243, +161,246,132,58,20,166,105,6,196,116,42,9,199,182,79,105,245,183,239,248,249,48,59,22,12,189,133,91,115,243,216,109,52,176,188,252,4,169,75,105,168,185,241,83,30,166,161,35,167,102,66,253,25,151,88,118,23,173,195,195,128,200,38,48,208,145,97,4,180,111, +154,198,115,60,153,2,245,230,47,220,185,139,198,246,54,150,150,202,72,164,134,161,170,57,95,87,8,100,207,163,165,29,4,60,24,151,184,212,69,183,219,13,136,97,239,254,141,90,237,21,207,39,162,4,193,165,184,247,96,145,23,81,46,63,134,50,148,64,169,88,232, +233,197,184,132,122,147,172,115,128,206,138,173,173,23,60,219,238,9,100,17,184,191,248,144,23,177,127,224,119,28,230,207,184,126,231,150,21,201,221,221,88,223,224,185,211,165,24,82,36,76,207,204,224,117,237,101,168,63,239,220,101,157,71,4,255,19,213, +106,149,103,195,180,60,111,59,212,159,113,9,229,123,110,93,200,247,251,217,218,211,158,26,229,123,78,233,185,14,87,212,193,184,132,221,229,253,47,159,251,14,103,92,162,235,237,71,222,24,200,159,204,111,1,6,0,203,214,249,255,62,204,159,178,0,0,0,0,73, +69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_neutral04_png = (const char*) temp_3b6cd20; + +//================== RadioButtons_neutral-05.png ================== +static const unsigned char temp_3c4e4a1[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,30,0,0,0,19,8,6,0,0,0,135,174,189,124,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,194,73,68,65,84,120,218,188,148,91,75,84,81,20,199,255,51,115,102,6,109,102,116,102,196,75,134,153,121,137,202,212,215,208,34,178,94,130,82,169,135,32,8,66,177,94,162,190,69,31,161,151,192,72,66,10,42,122,52,10,223,203,91, +50,163,134,118,70,71,207,164,168,103,46,103,198,115,63,237,189,213,129,156,139,16,53,11,54,103,159,181,214,94,191,181,214,190,216,154,155,154,34,40,161,200,154,58,166,107,250,51,219,181,171,189,214,149,222,235,165,129,202,50,222,189,29,219,221,22,197, +41,206,225,112,192,229,118,151,4,76,57,119,239,221,47,123,53,242,162,139,179,219,237,112,151,8,76,133,178,130,193,160,206,192,78,167,179,148,219,12,155,205,6,6,118,185,92,5,157,150,22,195,104,110,59,155,253,223,218,16,160,235,58,106,235,27,138,6,183, +52,25,130,32,160,254,100,83,46,152,12,59,165,211,125,206,55,118,211,73,60,126,242,20,194,106,36,171,235,234,236,196,131,193,33,100,210,169,28,255,95,194,26,84,69,102,182,27,55,111,97,232,225,163,188,113,73,201,197,193,110,231,94,39,6,135,135,145,216, +222,132,156,73,163,189,179,139,233,28,176,152,142,250,9,107,81,68,249,101,244,15,12,160,186,42,128,227,181,53,72,198,227,216,17,197,188,113,105,197,28,225,178,158,31,22,33,186,130,134,134,19,152,155,157,129,97,24,240,250,124,100,17,199,108,84,215,127, +251,14,155,191,30,29,69,95,127,31,252,126,63,251,191,216,221,195,190,83,223,190,66,76,166,243,198,166,194,25,186,129,76,38,147,99,56,213,216,72,130,116,99,226,203,103,114,248,92,8,4,2,224,249,8,76,146,68,116,53,138,115,231,219,153,95,77,77,53,42,72,82, +84,191,48,63,79,146,179,161,165,245,12,98,66,12,166,157,43,116,159,45,78,209,84,196,73,75,14,11,77,230,251,220,28,50,170,14,121,71,132,63,24,0,185,244,152,153,153,134,78,32,116,80,169,171,171,99,243,8,255,19,147,211,179,168,244,30,195,169,211,45,48,76, +3,137,68,42,47,120,151,130,77,195,132,170,170,57,70,170,155,156,156,102,243,170,64,37,122,46,93,38,175,206,27,72,169,20,9,24,207,250,53,183,182,97,113,62,12,73,146,216,154,148,100,49,189,73,118,50,95,92,118,226,45,139,180,154,100,166,20,112,56,16,113, +191,35,23,58,58,88,187,221,229,190,63,236,203,75,203,16,54,183,216,220,235,171,96,45,23,98,27,133,175,26,5,179,138,21,165,40,184,42,184,119,112,60,30,15,56,206,9,97,157,71,40,20,102,213,123,61,229,72,43,90,54,134,176,190,198,70,209,59,206,192,180,226, +35,192,60,191,130,247,31,62,34,65,174,200,65,245,227,227,159,254,250,229,218,107,53,219,99,229,72,231,31,139,11,255,236,201,220,7,27,5,15,193,255,16,113,103,11,73,73,42,227,116,77,195,122,116,181,36,80,141,176,66,225,144,106,154,230,115,46,153,76,188, +36,163,100,21,19,232,68,44,22,27,249,45,192,0,199,255,94,204,221,247,116,245,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_neutral05_png = (const char*) temp_3c4e4a1; + +//================== RadioButtons_selected-01.png ================== +static const unsigned char temp_647cc073[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,19,8,6,0,0,0,241,148,15,247,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,134,73,68,65,84,120,218,196,86,75,104,19,81,20,61,47,153,76,147,104,90,146,214,106,68,65,116,81,116,99,43,72,109,87,21,139,65,171,82,161,152,44,20,233,39,70,10,69,219,69,161,16,138,96,65,186,112,227,82,139,248,87,106,53,169, +46,20,252,130,138,40,45,88,41,46,130,198,66,193,79,98,205,111,38,49,153,207,115,146,148,34,152,31,166,140,15,238,48,188,251,206,187,231,157,185,239,222,33,148,82,88,173,214,147,235,170,140,221,162,76,77,80,121,48,74,240,83,134,10,118,104,120,231,6,118, +179,153,81,53,248,217,169,16,152,53,149,198,195,103,246,108,100,183,212,48,106,31,30,68,75,192,24,12,122,182,97,61,139,255,49,52,105,2,32,4,172,158,148,4,24,159,183,160,110,101,2,91,205,137,229,83,64,137,15,70,95,124,177,135,111,70,251,128,19,225,80, +8,179,30,55,234,87,197,203,39,160,81,84,72,191,104,117,164,160,121,226,205,176,57,156,32,137,5,88,170,45,168,61,56,130,247,33,99,81,92,49,35,26,162,16,80,20,208,48,36,175,221,137,52,193,102,119,2,63,125,168,124,53,8,157,207,147,33,81,179,127,4,51,63, +140,5,177,197,140,16,146,85,64,163,205,109,183,23,118,96,247,98,112,243,204,104,102,206,56,127,31,236,71,111,134,132,165,237,52,222,5,13,121,241,105,123,238,207,239,203,212,1,81,16,169,204,7,114,126,163,214,142,46,200,129,89,152,223,14,65,254,99,190, +226,195,24,104,138,71,85,157,3,66,235,48,94,123,7,208,104,141,252,133,191,28,220,133,3,221,125,144,31,180,231,78,2,73,2,35,136,2,13,7,131,57,253,250,199,39,144,252,50,133,112,46,103,240,28,228,104,4,150,109,61,16,219,70,241,232,106,15,182,215,134,150, +220,55,185,125,232,112,245,34,250,245,19,72,158,253,197,164,17,12,85,142,22,227,114,95,195,152,111,58,157,171,249,211,248,205,21,48,73,9,181,77,46,224,200,24,94,92,232,66,189,37,138,123,116,47,14,29,31,4,247,125,14,140,247,40,98,121,246,16,69,89,33,160, +244,130,8,167,249,247,187,244,242,6,86,164,73,180,244,2,206,139,152,188,123,13,118,87,63,184,111,159,193,95,239,44,120,128,37,2,49,142,150,117,159,99,207,110,33,153,38,97,235,131,253,88,191,34,187,31,129,243,157,69,113,66,150,0,16,79,208,178,139,74,252, +201,56,82,41,9,166,77,13,152,187,228,46,9,35,137,52,171,0,207,211,101,41,173,252,195,9,229,57,81,242,122,81,82,20,72,73,50,247,52,160,67,163,73,84,189,25,101,114,32,250,75,112,79,250,5,79,108,173,1,171,85,110,138,73,65,6,89,252,35,106,169,54,232,28,74, +103,210,171,173,194,111,1,6,0,169,191,241,34,56,210,107,35,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected01_png = (const char*) temp_647cc073; + +//================== RadioButtons_selected-02.png ================== +static const unsigned char temp_648ad7f4[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,102,73,68,65,84,120,218,196,150,77,104,19,65,20,199,255,187,153,181,201,134,212,24,42,126,32,86,15,133,10,69,26,40,162,17,84,68,41,10,18,84,90,171,205,69,37,135,74,241,82,240,3,188,120,241,100,241,224,199,69,17,60,104,75, +43,22,105,197,70,35,226,71,139,7,17,63,138,20,139,208,18,164,24,107,178,105,178,155,110,146,221,117,102,11,10,238,166,132,180,164,11,111,118,118,222,188,249,241,248,207,155,89,210,88,183,121,18,203,244,144,237,155,106,106,187,154,86,85,28,220,253,62, +9,194,57,56,172,16,249,138,195,25,151,240,180,169,114,85,30,206,184,243,153,59,185,5,39,246,255,172,197,198,109,205,16,4,1,223,71,134,208,178,102,106,105,50,231,104,210,196,89,124,210,128,28,64,176,51,12,66,136,249,221,224,111,194,96,239,109,28,118,143, +46,14,78,185,60,199,115,112,8,246,246,52,190,1,205,109,97,24,121,5,174,72,135,105,172,207,198,134,103,183,20,141,43,197,24,151,231,56,218,16,171,77,41,110,4,66,151,192,25,26,188,163,23,192,27,138,105,102,159,170,180,179,173,11,159,102,68,219,216,82,204, +228,206,139,111,53,169,254,20,221,136,78,8,159,239,128,215,229,127,62,218,23,198,123,168,254,4,238,189,23,145,202,241,182,241,108,252,254,180,31,147,25,209,214,111,214,57,180,28,116,57,110,209,100,109,141,23,249,175,143,225,137,13,65,255,207,231,156, +120,0,73,172,199,234,245,91,17,205,6,112,84,127,100,137,127,171,183,224,224,137,118,168,239,110,64,79,70,173,162,107,26,72,65,157,131,244,75,177,248,92,79,142,155,111,169,200,134,17,95,159,131,18,236,195,174,67,237,232,191,62,130,253,190,177,191,190, +231,137,6,236,238,60,134,57,105,26,174,111,61,182,107,20,84,145,194,11,58,210,25,174,140,253,154,65,213,240,121,240,193,155,216,17,238,198,155,107,173,104,244,205,226,99,162,26,254,142,43,112,56,120,228,31,158,68,58,103,191,54,227,154,240,84,89,112,250, +76,140,193,253,234,22,86,238,57,131,186,240,93,68,158,13,98,95,168,21,213,30,15,146,145,171,200,38,100,86,84,197,225,121,51,115,163,236,122,77,191,236,133,170,106,88,119,224,44,142,132,78,195,65,75,97,102,224,50,226,31,162,11,198,49,46,209,10,6,148,172, +177,168,3,67,121,209,135,31,212,156,94,31,213,57,81,82,12,227,146,130,166,67,150,141,37,57,175,101,249,119,201,115,25,215,212,92,206,26,21,191,88,76,205,213,188,142,47,169,202,223,106,140,75,98,178,113,47,38,107,203,242,39,243,71,128,1,0,163,90,231,150, +52,232,169,252,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected02_png = (const char*) temp_648ad7f4; + +//================== RadioButtons_selected-03.png ================== +static const unsigned char temp_6498ef75[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,1,190,73,68,65,84,120,218,196,150,189,79,194,80,20,197,207,43,79,144,26,163,68,6,29,140,50,24,29,77,208,196,56,56,184,57,27,157,116,112,116,246,223,80,255,5,227,226,234,224,199,164,51,241,35,58,56,104,116,129,176,16,48,10,161, +69,90,222,135,125,69,166,190,130,96,130,55,13,29,238,61,231,215,155,243,82,74,230,103,82,89,252,83,209,165,233,228,212,222,66,162,239,224,131,251,79,80,18,33,136,154,70,223,225,138,75,13,239,39,22,239,63,92,113,155,155,15,146,64,243,170,48,140,34,27, +106,159,153,116,177,57,249,209,251,230,196,91,154,14,6,155,35,203,219,88,73,47,118,62,52,103,59,189,193,21,151,24,4,145,1,162,233,18,100,174,207,177,54,250,172,21,223,84,38,48,187,186,165,215,254,10,174,54,247,32,6,13,49,16,12,242,243,69,47,254,137,36, +84,219,9,238,113,105,51,252,118,7,35,164,193,9,58,105,31,10,113,164,70,28,36,226,66,31,25,184,11,97,23,131,75,155,14,134,163,18,162,90,212,10,221,134,5,193,185,86,219,170,92,114,23,111,239,57,108,136,75,205,195,115,80,230,212,81,46,213,2,189,244,215, +62,164,107,161,236,86,181,198,182,81,5,243,12,202,165,82,40,60,146,138,129,145,168,118,134,57,166,7,103,2,85,75,147,155,85,104,165,163,53,102,38,247,239,90,109,171,164,119,73,169,157,81,92,31,94,177,186,63,52,46,109,230,120,241,58,16,58,51,62,199,33, +133,212,250,251,240,134,191,185,236,26,30,27,107,26,174,31,92,181,157,187,187,60,209,250,43,46,229,76,162,246,213,61,220,204,102,80,127,56,237,56,55,116,123,140,90,61,232,175,184,148,113,1,219,238,30,14,187,134,199,163,195,158,223,237,138,235,103,110, +247,176,249,95,203,207,220,105,8,60,85,250,255,175,166,184,52,111,203,227,188,205,255,229,75,230,91,128,1,0,165,175,191,223,100,163,205,167,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected03_png = (const char*) temp_6498ef75; + +//================== RadioButtons_selected-04.png ================== +static const unsigned char temp_64a706f6[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,100,73,68,65,84,120,218,196,150,77,104,211,96,24,199,255,111,154,102,205,92,221,186,85,17,71,173,58,198,188,232,6,14,84,148,162,172,226,7,76,70,65,119,216,209,195,64,60,41,130,99,87,15,122,24,168,7,5,79,83,97,8,165,155,122, +17,199,16,25,58,61,104,81,118,152,173,171,19,183,22,109,221,154,146,164,31,107,154,248,38,21,81,147,94,180,235,2,239,75,194,147,252,127,255,231,125,222,143,144,174,246,29,159,177,78,23,187,127,187,219,123,177,219,85,115,240,200,155,52,88,98,35,224,234, +153,154,195,117,46,203,208,174,142,175,61,92,231,150,51,119,16,83,240,125,154,71,68,226,225,223,180,130,102,199,26,101,78,104,210,172,133,184,224,245,163,239,88,0,175,94,76,35,30,158,68,239,150,4,92,188,86,61,184,206,37,12,129,205,78,44,198,133,65,124, +105,17,173,91,91,113,224,208,21,195,196,242,135,25,28,119,127,132,203,161,85,1,174,103,78,8,24,214,2,78,245,191,39,191,193,39,222,131,196,6,168,9,15,53,113,25,11,177,24,66,83,227,232,105,138,160,173,229,223,77,24,220,114,241,205,237,215,0,168,50,54,198, +238,163,51,113,19,182,197,231,160,165,66,255,224,37,136,221,67,184,243,105,23,22,210,196,242,123,189,101,86,25,188,75,241,21,245,89,148,86,161,202,73,147,51,167,83,67,177,88,248,45,150,68,131,48,130,61,156,19,66,238,20,150,69,15,78,159,189,128,249,104, +20,143,158,60,192,137,230,89,116,184,139,127,104,76,138,39,193,185,189,232,146,111,155,83,47,149,192,42,133,60,132,84,214,20,219,157,185,5,194,53,64,144,82,127,69,232,115,252,58,246,210,59,158,27,64,1,251,48,112,126,24,209,185,57,4,31,222,197,209,13, +97,116,180,228,141,55,21,158,3,111,175,131,176,148,50,233,43,133,122,10,87,84,136,146,69,205,33,253,108,164,98,221,196,151,99,240,98,12,92,238,12,52,254,32,6,135,174,26,38,110,140,143,194,103,11,67,107,215,140,185,99,165,175,115,13,120,70,34,255,53,115, +51,211,65,52,33,8,53,29,128,218,232,195,185,225,107,134,9,123,34,94,142,87,130,23,141,204,171,179,126,197,103,33,58,137,66,200,38,251,160,110,62,130,195,61,126,188,125,61,99,169,175,115,217,146,162,33,155,211,170,186,123,205,79,77,208,126,2,43,95,122, +225,201,103,241,213,66,95,231,178,74,73,133,44,107,107,178,127,71,158,62,174,24,211,185,70,205,229,156,86,243,131,197,168,121,161,168,98,54,83,251,83,77,231,146,206,157,219,70,215,235,79,230,135,0,3,0,71,200,242,251,63,187,157,122,0,0,0,0,73,69,78,68, +174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected04_png = (const char*) temp_64a706f6; + +//================== RadioButtons_selected-05.png ================== +static const unsigned char temp_64b51e77[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,30,0,0,0,19,8,6,0,0,0,135,174,189,124,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,242,73,68,65,84,120,218,188,85,93,72,20,81,20,254,102,118,212,93,93,117,253,163,52,127,211,53,243,167,52,130,10,37,235,37,122,232,7,163,16,234,41,138,18,31,244,33,159,130,222,123,14,42,31,132,126,164,63,159,202,34,136,160, +20,77,68,197,214,108,93,17,117,215,118,213,214,85,217,93,103,118,119,118,254,154,185,146,32,142,74,16,123,224,114,238,61,223,153,243,205,57,247,222,115,169,106,107,145,11,49,148,181,168,248,154,227,133,251,204,241,194,204,130,59,71,211,98,66,26,140,42, +104,254,244,171,133,23,214,234,24,202,64,33,62,145,142,9,113,102,34,208,209,80,100,186,214,53,93,195,208,42,113,130,137,142,89,169,179,76,192,190,76,139,184,158,177,145,66,76,69,165,163,41,53,89,198,184,253,248,188,96,220,180,238,99,115,209,25,168,217, +241,27,109,116,39,156,71,231,74,133,46,70,81,148,70,76,193,16,167,63,134,35,197,168,111,125,140,39,139,21,27,182,196,154,6,52,222,108,193,68,36,123,139,191,109,137,70,80,162,9,118,246,194,37,52,54,181,233,198,213,132,33,236,140,126,169,151,227,11,136, +110,188,213,134,119,175,30,160,216,180,138,170,234,35,196,246,147,170,196,168,255,32,174,103,246,96,196,67,97,52,90,134,51,87,110,96,216,62,78,240,116,191,31,249,146,3,138,94,108,213,196,104,154,54,108,197,250,231,45,160,115,178,97,31,251,14,81,146,64, +167,228,128,103,226,8,166,217,206,93,190,74,230,31,95,122,80,126,177,9,141,105,235,87,242,68,221,73,162,109,195,131,40,96,59,64,25,244,183,153,129,20,133,204,45,109,1,148,188,115,168,173,59,141,161,47,221,80,226,205,72,74,223,139,57,231,2,74,212,159, +240,185,167,32,87,30,34,126,209,172,106,164,166,164,64,86,237,238,201,17,240,180,25,37,165,101,240,255,118,66,166,150,116,73,121,62,162,48,34,31,129,223,23,218,2,86,5,30,193,105,75,70,57,215,139,254,149,42,152,50,242,32,208,73,24,179,141,130,18,66,164, +10,154,236,201,206,37,115,215,236,12,172,67,173,248,106,105,70,97,177,21,201,194,18,252,1,159,46,113,56,108,80,137,69,25,107,172,222,30,179,72,31,184,71,102,166,236,42,212,214,159,194,135,174,231,96,131,65,48,171,211,27,94,37,165,7,48,229,176,3,1,15, +137,147,64,57,137,61,149,247,110,19,87,173,166,162,128,16,7,216,93,238,177,111,157,168,172,250,24,22,102,28,56,44,207,110,130,87,28,3,216,239,124,129,128,122,106,74,141,147,112,255,248,134,4,87,15,89,235,137,44,171,196,2,201,88,217,145,215,146,33,18, +109,54,155,145,33,47,195,231,114,65,26,124,131,32,199,67,204,176,34,223,219,187,17,99,141,85,223,28,215,93,240,59,196,83,52,98,73,84,16,10,239,76,140,201,62,204,181,223,6,239,247,66,242,175,66,59,17,161,183,15,55,224,208,63,54,174,245,82,75,50,56,78, +217,213,153,179,79,252,183,142,41,255,221,99,46,172,196,172,77,123,162,6,120,217,176,137,225,5,25,227,129,216,188,78,188,12,188,159,143,68,213,42,183,51,110,78,121,230,230,164,152,101,44,72,82,207,226,226,226,211,63,2,12,0,110,51,67,131,64,218,62,45, +0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected05_png = (const char*) temp_64b51e77; + +//================== RadioButtons_selected_over-01.png ================== +static const unsigned char temp_4d6e0f0c[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,19,8,6,0,0,0,241,148,15,247,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,239,73,68,65,84,120,218,196,86,93,72,20,81,20,254,238,236,236,56,179,174,43,91,130,187,130,136,97,81,22,244,3,105,8,134,105,168,245,32,229,147,15,10,25,37,173,81,212,67,15,86,15,65,68,244,212,83,62,244,24,65,68,166,32,18, +132,63,69,17,82,61,20,171,65,81,216,139,144,238,34,106,59,59,251,51,51,247,118,103,86,130,220,137,149,86,182,129,195,12,115,206,61,223,119,190,57,247,204,37,140,49,4,131,193,75,213,91,188,251,240,31,46,145,131,223,80,138,164,129,211,117,85,82,169,34, +21,20,124,232,211,34,196,128,207,211,125,251,216,54,169,182,76,228,175,88,65,9,188,248,46,66,84,20,89,218,95,185,193,202,201,218,125,147,120,10,46,2,17,132,64,146,73,110,96,129,96,116,177,12,53,94,13,181,197,26,64,89,222,68,136,69,128,227,67,148,115, +160,187,128,9,52,162,61,212,139,164,22,193,220,248,45,236,144,99,128,153,159,28,68,224,117,89,15,46,55,113,54,137,155,66,48,229,106,68,195,241,94,184,233,44,148,98,63,202,90,175,99,14,62,219,103,199,184,255,205,8,87,85,176,10,20,68,146,109,86,80,17,193, +36,175,252,80,27,7,79,77,163,120,246,30,228,31,79,161,120,252,240,31,185,134,175,166,207,142,177,98,29,115,228,48,66,72,70,1,193,149,109,132,7,60,215,27,81,119,244,20,196,228,52,188,159,31,128,252,212,33,127,155,224,36,134,33,91,36,14,95,197,151,180, +15,2,87,193,41,135,192,55,214,235,121,1,130,69,82,204,246,219,115,192,208,13,70,227,145,236,15,36,11,56,216,220,3,33,254,18,222,240,93,208,24,255,214,122,198,37,133,31,130,166,84,208,202,110,148,52,92,65,120,98,0,123,228,229,76,79,176,181,158,224,13, +54,164,182,162,165,39,4,246,174,19,44,206,223,27,235,250,197,52,33,234,134,206,86,162,209,236,6,225,178,42,239,67,48,22,194,88,81,121,94,125,157,63,114,31,228,128,10,105,251,25,148,54,221,196,219,209,126,236,116,45,129,165,153,221,89,99,228,36,218,186, +250,144,142,133,161,174,70,96,68,25,152,241,103,14,35,229,129,200,40,16,83,137,99,243,147,15,51,176,252,160,206,219,148,188,122,132,162,52,133,103,119,31,42,58,6,49,51,28,66,53,91,198,148,208,129,246,174,203,160,218,44,92,111,206,99,101,129,128,38,178, +55,140,97,80,78,128,75,182,170,10,27,152,62,206,46,97,242,49,252,60,145,103,239,57,84,117,14,226,227,244,24,218,91,206,218,224,169,241,11,72,112,112,61,110,129,103,231,249,77,32,166,230,49,81,120,222,216,179,39,40,79,82,148,212,247,163,206,6,159,193, +210,200,69,104,11,12,70,130,75,111,58,47,213,51,4,0,45,145,231,72,227,242,106,99,67,8,38,77,148,214,236,194,252,232,29,104,81,10,211,2,167,127,95,102,242,166,180,21,136,199,55,103,184,171,35,195,246,76,128,201,96,234,185,135,164,97,114,5,210,38,85,167, +34,110,212,151,24,155,244,143,219,120,49,86,15,144,64,32,112,130,63,143,52,87,40,40,47,236,113,0,95,227,156,192,218,137,168,105,171,226,238,226,127,38,185,208,39,162,95,2,12,0,137,200,31,90,212,72,119,82,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected_over01_png = (const char*) temp_4d6e0f0c; + +//================== RadioButtons_selected_over-02.png ================== +static const unsigned char temp_4d7c268d[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,216,73,68,65,84,120,218,196,149,79,72,84,65,28,199,191,51,239,237,190,221,183,184,166,22,145,84,70,137,97,90,33,107,218,22,129,18,17,29,162,67,66,209,255,78,117,137,14,29,11,138,200,110,17,116,232,84,80,116,8,73,41,188,164, +93,182,63,104,148,34,149,186,176,22,37,122,200,63,152,171,187,179,239,173,251,254,52,111,246,80,235,110,82,107,232,240,230,49,204,252,230,247,249,205,124,103,126,67,130,91,202,31,96,153,138,188,110,165,255,116,83,213,234,37,7,183,14,142,67,46,81,101, +212,151,218,11,91,146,223,27,182,248,22,91,66,223,100,200,84,34,80,188,244,207,86,124,136,184,9,136,146,182,177,231,44,94,57,221,92,28,220,225,202,132,255,220,30,146,219,66,226,96,159,132,110,115,51,214,84,55,138,174,177,112,8,65,41,2,59,110,1,70,254, +91,64,4,156,47,72,246,228,10,141,7,164,82,244,120,26,16,8,158,128,36,105,162,187,116,125,45,62,188,127,132,128,251,53,16,231,203,183,242,11,64,112,9,135,72,46,146,173,49,223,230,94,115,19,170,56,152,90,227,80,223,54,11,173,217,206,43,168,172,59,137,143, +93,81,212,20,124,2,209,204,188,206,128,195,165,132,240,159,156,89,37,133,96,194,229,71,69,227,5,46,121,20,254,222,102,208,4,3,213,24,252,61,55,32,145,4,202,119,157,195,8,10,33,169,18,168,43,219,135,211,39,121,210,53,215,184,224,166,197,207,172,196,77, +193,54,28,231,109,47,92,159,31,3,90,2,148,91,58,149,232,12,174,225,167,188,77,225,13,92,4,83,228,180,243,121,62,98,252,192,116,36,131,248,46,21,130,186,179,199,197,61,135,57,7,139,77,100,238,73,138,160,192,231,3,134,159,193,243,229,57,108,211,206,216, +89,37,220,130,184,186,17,74,113,29,194,174,61,168,213,91,120,128,246,47,253,121,48,253,5,71,80,87,127,20,214,208,29,88,35,33,238,115,158,54,166,9,217,72,234,136,78,38,178,52,119,183,159,17,190,162,86,110,205,148,55,87,161,31,184,143,178,170,38,116,191, +232,66,117,162,15,150,19,0,159,219,75,106,176,189,225,16,76,109,0,158,72,11,162,51,124,194,60,63,70,82,229,112,195,66,44,78,254,253,196,176,24,188,47,175,131,238,187,133,242,189,215,16,110,59,139,50,250,3,17,182,2,149,199,46,67,150,116,24,157,151,16, +29,35,176,83,217,211,29,174,128,207,228,3,231,37,54,48,128,194,162,123,240,4,206,99,237,193,187,136,12,190,66,197,182,253,80,20,31,180,190,219,152,253,154,128,161,147,156,183,65,192,83,98,229,249,39,139,88,199,19,172,226,89,175,120,247,41,108,221,113, +152,175,120,22,147,161,155,152,126,23,130,33,206,65,238,121,14,87,54,121,150,74,104,139,72,214,60,247,176,246,86,140,116,182,65,45,41,130,30,157,134,153,180,97,25,88,240,254,59,92,217,48,45,48,246,31,94,138,152,141,217,169,169,116,251,47,220,57,92,161, +57,211,236,37,127,82,133,230,201,148,133,254,25,186,228,112,135,43,143,50,251,225,40,51,177,28,229,167,0,3,0,110,188,26,228,110,165,221,163,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected_over02_png = (const char*) temp_4d7c268d; + +//================== RadioButtons_selected_over-03.png ================== +static const unsigned char temp_4d8a3e0e[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,101,73,68,65,84,120,218,196,150,61,143,211,64,16,134,223,89,111,226,195,7,220,33,78,66,128,34,16,80,5,209,32,1,66,162,165,161,166,160,65,80,208,242,51,248,13,84,72,92,139,104,168,40,40,174,58,10,26,78,66,87,33,133,143,0,34, +137,20,146,216,107,39,142,215,203,172,147,226,108,135,128,41,114,43,37,78,188,51,243,236,188,51,187,54,221,108,94,122,142,67,26,178,177,117,252,193,221,203,167,86,14,126,185,223,129,60,233,73,220,56,99,86,14,223,249,36,33,133,67,112,143,136,242,44,21, +174,197,97,10,215,138,195,114,37,241,87,125,173,64,144,132,221,225,9,248,114,99,105,240,116,28,226,206,86,23,152,86,95,1,101,112,78,90,174,21,82,94,23,56,125,245,33,174,157,187,242,247,166,217,121,4,4,105,101,9,50,46,9,130,83,163,188,220,158,128,235, +74,252,104,189,65,83,190,227,20,169,84,146,47,73,3,27,23,239,195,177,37,139,25,110,168,34,220,102,78,4,33,243,112,226,255,105,106,16,169,4,102,244,25,52,77,243,229,118,4,166,199,182,178,223,14,203,103,172,127,69,229,45,87,206,138,159,207,138,230,253, +103,23,32,248,83,12,76,198,64,207,213,176,190,198,89,172,250,94,111,29,231,55,199,216,172,235,133,243,18,58,70,170,186,7,151,196,17,9,113,20,160,142,241,108,46,41,120,114,182,177,244,145,106,13,29,253,4,148,93,96,217,166,215,184,135,142,255,21,183,227, +87,92,154,194,60,251,202,100,50,198,160,23,230,51,27,18,46,196,79,96,194,16,131,95,62,75,80,88,50,103,26,50,60,225,0,126,191,3,221,71,201,134,92,1,239,172,135,4,46,70,237,30,39,145,135,39,19,143,225,73,10,63,40,52,139,98,231,65,151,147,49,229,102,179, +129,107,124,91,207,104,97,200,42,4,101,59,193,211,130,21,36,50,240,21,247,80,144,143,97,185,25,124,24,252,169,83,23,223,23,53,147,57,219,241,246,155,135,81,79,115,127,228,109,92,143,213,187,158,102,181,14,88,216,169,202,55,101,6,159,102,153,87,107,85, +81,199,172,83,121,220,122,252,122,169,237,247,253,22,2,86,50,83,231,0,198,114,165,230,102,10,163,138,7,68,12,28,253,184,11,209,220,230,147,202,192,164,139,183,146,165,209,251,23,240,71,188,59,162,60,220,114,101,194,181,83,170,234,38,5,162,150,66,255, +233,51,62,35,150,31,110,188,153,144,140,121,129,186,80,115,61,175,185,138,254,243,233,48,250,71,191,5,102,89,205,39,124,122,125,24,138,149,63,82,45,87,182,149,217,110,43,125,40,111,50,191,5,24,0,98,67,27,130,54,13,67,66,0,0,0,0,73,69,78,68,174,66,96, +130,0,0 }; + +const char* BinaryData::RadioButtons_selected_over03_png = (const char*) temp_4d8a3e0e; + +//================== RadioButtons_selected_over-04.png ================== +static const unsigned char temp_4d98558f[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,31,0,0,0,19,8,6,0,0,0,104,108,214,66,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,2,211,73,68,65,84,120,218,196,150,205,75,20,97,28,199,191,207,204,179,186,179,187,90,90,184,100,25,26,43,149,122,176,64,74,33,37,148,204,50,12,234,84,135,110,65,151,110,29,252,51,58,132,208,169,46,5,33,228,91,210,139,96,16, +145,93,180,178,14,97,104,33,42,235,186,235,174,59,179,187,243,246,60,61,179,43,184,57,219,69,86,125,96,102,96,158,121,158,207,247,247,250,12,105,109,8,61,193,62,13,90,115,184,252,206,205,198,224,158,131,7,127,132,65,15,249,40,206,85,243,61,135,79,46, +80,80,73,38,40,85,164,194,95,144,205,231,46,104,115,184,148,136,91,137,151,184,38,103,55,124,248,109,6,208,17,140,162,156,48,192,22,10,88,241,224,36,11,23,70,83,175,219,100,45,120,9,221,237,125,152,159,155,198,244,247,55,56,31,152,71,128,217,128,133, +162,184,35,203,37,18,129,236,33,46,119,123,60,50,52,53,140,234,234,74,156,168,239,199,194,175,25,68,126,78,160,197,63,135,114,238,120,130,229,248,124,167,112,199,114,66,32,81,55,220,185,82,106,12,33,227,49,82,122,39,42,42,27,81,119,245,1,214,99,203,248, +244,121,24,77,100,6,199,21,27,220,218,153,35,28,46,205,5,191,112,162,49,198,33,165,117,148,173,140,160,172,100,2,42,235,22,139,78,162,173,231,30,98,209,37,140,77,141,160,217,243,5,53,66,68,54,39,182,9,88,207,72,248,147,84,208,124,36,37,54,115,231,12, +133,109,128,105,171,219,101,193,235,51,96,100,84,112,117,25,44,206,178,177,86,194,3,168,13,4,144,172,189,134,12,59,141,182,203,119,17,93,91,196,224,199,65,156,149,166,80,231,55,192,77,228,64,98,188,85,123,112,240,88,8,220,243,72,236,35,94,164,243,232, +182,13,106,233,25,196,35,41,151,91,78,101,6,64,82,85,72,172,133,133,184,60,213,68,8,157,127,136,163,10,129,114,230,58,86,104,7,46,244,222,199,218,106,31,158,127,120,134,38,243,61,106,60,58,184,33,22,248,189,80,252,10,82,198,50,44,85,134,29,219,218,223, +210,125,2,110,49,36,85,119,169,137,108,3,9,11,203,185,3,46,48,159,0,54,222,13,225,64,233,48,148,150,62,176,64,59,58,111,244,35,186,122,11,227,66,68,200,152,132,167,2,144,101,9,134,45,33,157,38,48,213,60,184,224,102,225,137,66,112,87,167,249,255,116,226, +245,144,40,215,97,200,109,189,176,43,46,162,203,17,17,185,141,170,200,18,188,94,9,122,66,130,150,22,2,84,254,47,220,204,90,94,132,22,38,113,196,71,71,33,123,199,96,117,244,192,14,118,161,190,161,21,209,240,55,232,134,4,85,117,170,103,139,227,112,169, +109,113,164,210,69,236,159,73,142,228,203,87,66,196,56,202,58,175,192,79,85,68,23,8,212,117,6,61,143,227,112,169,37,154,133,166,237,66,243,222,224,248,250,98,12,114,73,174,166,109,131,131,153,121,49,183,55,99,174,165,119,249,84,35,238,30,144,141,185, +110,50,204,38,164,61,63,82,29,46,93,212,248,211,69,205,222,151,63,153,191,2,12,0,199,181,70,142,38,155,205,86,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected_over04_png = (const char*) temp_4d98558f; + +//================== RadioButtons_selected_over-05.png ================== +static const unsigned char temp_4da66d10[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,30,0,0,0,19,8,6,0,0,0,135,174,189,124,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97, +100,121,113,201,101,60,0,0,3,94,73,68,65,84,120,218,188,85,93,104,19,89,20,254,238,204,157,100,38,77,108,173,105,107,250,71,45,117,101,119,117,65,163,86,65,65,80,31,84,16,138,34,203,10,250,164,176,248,226,155,111,203,62,238,211,190,44,136,136,15,46,138, +15,190,46,116,5,65,42,42,34,40,162,134,86,219,90,163,77,77,39,177,209,73,50,153,76,146,153,241,100,82,139,109,38,138,15,102,224,48,247,156,123,238,249,238,249,206,185,247,178,157,63,13,93,70,19,191,148,110,206,235,102,249,47,222,23,94,117,242,232,207, +93,77,1,117,108,27,127,223,139,27,102,57,183,139,175,9,112,12,119,59,77,202,151,225,210,200,58,229,248,245,233,205,92,16,25,252,138,240,61,48,40,197,122,115,135,2,244,132,219,42,156,17,176,79,102,222,139,63,237,199,89,148,170,206,89,109,92,113,60,3,187, +128,228,195,72,156,170,143,151,31,249,8,140,130,113,217,67,2,12,188,93,196,125,61,8,30,20,192,21,210,87,139,136,41,131,24,117,118,212,230,101,246,217,154,69,157,236,82,7,199,195,200,175,248,223,138,46,250,45,143,205,24,171,2,51,136,210,10,241,145,4,4, +196,67,63,34,122,226,31,140,150,182,66,8,9,144,218,57,194,91,126,195,190,145,211,72,135,250,92,31,81,174,249,138,109,34,38,45,9,133,144,132,249,80,47,54,69,247,99,239,145,51,16,253,245,241,225,146,82,69,231,172,142,10,214,34,160,20,92,231,170,123,14, +255,142,187,55,207,99,136,127,64,123,120,208,181,37,90,135,241,52,99,226,64,235,13,76,105,2,230,165,109,216,112,224,24,212,76,28,2,37,227,43,230,209,89,124,184,68,253,202,248,220,45,165,184,162,6,180,171,113,179,19,66,75,63,50,233,73,88,150,13,121,77, +31,108,191,228,78,23,242,211,216,240,203,65,119,60,254,100,14,29,187,79,162,195,23,114,245,174,200,70,247,63,51,249,8,107,231,175,214,128,197,250,86,224,176,74,176,245,212,114,171,44,192,233,57,132,181,221,155,241,122,98,20,82,160,21,242,170,110,100, +242,42,130,150,5,35,59,1,89,169,177,225,143,108,135,40,6,96,147,93,95,184,75,134,126,180,4,251,241,94,157,129,157,163,184,78,125,7,154,102,209,225,21,179,136,15,233,194,242,25,218,97,127,225,60,18,80,16,121,127,19,111,74,195,212,96,131,112,4,5,201,185, +9,136,197,12,42,97,171,6,44,71,80,33,208,133,119,9,244,62,62,135,153,129,179,240,175,239,129,98,188,165,184,41,207,206,55,12,145,128,43,54,114,121,143,227,148,205,35,48,251,39,108,106,42,190,41,138,222,129,40,94,63,79,32,151,205,34,100,188,90,114,243, +201,93,72,171,211,48,212,41,104,170,0,83,153,2,214,3,10,177,152,203,121,31,83,135,88,112,129,181,124,131,115,76,141,39,217,128,165,189,116,213,214,206,40,230,94,62,193,128,57,177,204,77,141,141,161,43,118,5,26,141,59,91,198,161,190,184,13,223,244,45, +104,21,239,184,182,77,192,101,55,227,198,87,166,80,34,230,179,197,165,150,240,229,146,72,60,155,69,120,245,85,20,202,37,152,129,31,16,142,143,65,211,22,137,138,197,129,216,31,181,210,58,78,131,59,155,128,45,186,89,10,70,99,96,102,18,248,131,59,120,155, +58,5,35,147,70,49,149,65,117,27,218,181,139,85,66,220,216,142,237,125,61,54,124,44,92,170,233,168,232,250,87,86,17,35,217,133,231,223,20,252,75,159,253,169,198,186,225,52,237,61,78,148,68,168,121,67,225,102,217,198,51,77,104,10,168,73,37,249,111,174, +88,34,150,47,240,89,221,249,119,86,183,154,150,113,217,178,198,146,201,228,229,143,2,12,0,249,150,92,255,88,186,243,251,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::RadioButtons_selected_over05_png = (const char*) temp_4da66d10; + +//================== noise_wave.png ================== +static const unsigned char temp_9db0b117[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,4,101,0,0,2,30,8,6,0,0,0,18,223,178,102,0,0,0,9,112,72,89,115,0,0,23,18,0,0,23,18,1,103,159,210,82,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101, +97,100,121,113,201,101,60,0,0,76,229,73,68,65,84,120,218,236,221,235,149,21,55,214,48,96,13,203,255,221,95,4,212,68,64,59,2,202,17,24,71,48,77,4,47,142,192,77,4,120,34,160,39,2,112,4,20,17,24,34,112,57,2,67,4,243,181,56,167,135,6,250,114,46,117,145,180, +159,103,173,90,96,3,125,78,237,146,84,210,46,149,244,143,4,0,0,0,172,229,228,242,56,189,60,186,237,113,155,225,242,248,112,121,188,19,50,0,0,0,128,253,229,36,204,217,229,241,242,242,248,243,242,248,239,1,199,155,203,227,60,109,146,57,0,0,0,0,220,225, +236,242,120,149,14,75,194,220,117,228,196,206,121,186,123,150,13,0,0,0,64,40,121,86,204,121,58,124,70,204,190,71,158,125,211,9,59,0,0,0,16,217,217,229,241,119,90,38,25,35,57,3,0,0,0,132,151,215,121,249,35,173,147,140,185,126,228,132,208,51,151,3,0,0, +0,136,32,39,65,254,91,216,145,23,5,62,113,105,0,0,0,128,22,229,164,71,126,101,232,191,133,30,121,214,140,157,154,0,0,0,128,166,228,132,76,9,175,43,237,146,152,57,115,185,0,0,0,128,22,212,146,144,185,126,156,185,108,0,0,0,64,205,106,76,200,92,29,79,92, +62,0,0,0,160,86,175,82,157,9,25,107,204,0,0,0,0,213,122,145,234,77,200,92,29,127,38,187,50,1,0,0,0,21,233,83,253,9,153,235,219,101,179,162,127,8,1,0,5,56,221,30,221,229,241,40,221,253,212,230,221,229,241,241,242,24,182,191,255,32,124,0,192,66,114,31, +165,181,25,38,191,93,30,191,184,180,0,16,171,67,115,118,121,188,76,155,119,154,143,121,194,147,23,216,203,83,136,189,23,13,0,204,173,133,215,150,236,200,4,0,65,229,196,201,20,137,152,187,222,141,126,150,188,31,13,0,76,175,75,109,38,100,44,252,11,0,141, +235,211,230,157,229,37,59,22,231,73,114,6,0,152,206,146,125,25,11,255,2,0,71,203,55,246,151,105,221,167,62,207,92,6,0,224,72,93,106,59,33,99,225,95,0,104,204,89,154,239,53,165,67,58,24,157,75,2,0,28,104,205,135,76,75,31,47,92,110,0,168,215,218,179,99, +238,154,53,115,230,242,0,0,7,244,109,74,121,208,100,225,95,0,224,86,93,218,236,134,228,233,15,0,208,138,179,20,43,33,99,225,95,0,168,208,105,170,231,41,210,75,151,11,0,216,209,171,20,47,41,99,225,95,0,168,72,77,9,25,137,25,0,96,87,39,41,102,66,198,194, +191,0,80,137,46,213,251,158,181,196,12,0,112,151,103,41,118,82,198,171,223,0,80,176,252,244,168,244,53,100,238,59,206,93,70,0,224,22,181,247,115,44,252,11,0,13,107,229,29,235,39,46,37,0,240,149,46,73,198,88,248,23,0,10,117,214,88,71,195,66,118,0,192, +117,94,93,178,240,47,0,20,169,75,245,174,35,115,219,241,202,101,5,0,174,241,234,146,133,127,1,160,72,173,110,13,217,187,180,0,64,218,188,170,35,9,99,225,95,0,40,78,159,218,158,150,11,0,240,34,73,190,88,248,23,0,10,212,250,84,94,157,12,0,224,207,36,241, +98,225,95,0,40,204,89,138,177,136,29,0,16,151,87,151,44,252,11,0,197,57,73,113,158,26,245,46,55,0,132,229,213,37,11,255,2,64,113,206,3,117,48,94,186,220,0,16,86,107,59,76,90,248,23,0,42,215,5,235,160,252,237,146,3,64,72,79,36,89,172,201,7,0,165,121,25, +176,115,241,196,101,7,0,125,30,135,133,127,1,96,77,125,208,206,133,87,152,0,32,30,175,46,89,248,23,0,138,242,38,197,125,226,3,0,196,225,213,37,11,255,2,64,81,206,130,119,44,188,194,4,0,113,188,146,84,177,240,239,210,254,33,4,124,165,79,155,41,103,87, +239,3,62,76,155,5,62,179,119,151,199,199,107,191,31,183,191,2,109,202,109,193,31,215,218,128,136,126,187,60,126,81,20,0,32,68,191,199,44,217,233,60,189,60,46,132,1,238,151,147,47,47,182,3,175,99,166,168,61,75,22,118,130,214,156,39,79,122,254,84,12,0, +32,132,51,253,30,11,255,194,82,186,109,34,230,207,153,6,48,57,65,99,129,39,168,191,157,176,208,221,230,208,161,0,128,246,121,117,201,194,191,176,200,32,107,201,45,222,94,166,216,175,61,64,205,108,7,233,189,104,0,136,226,68,127,199,194,191,48,119,35,179, +230,0,235,60,201,144,66,77,122,29,8,175,48,1,64,32,207,244,119,60,224,130,57,27,152,18,94,65,200,223,193,46,38,80,135,168,91,96,123,133,9,0,98,58,102,125,77,135,29,45,225,70,121,102,74,137,239,69,190,76,102,205,64,201,206,116,26,110,60,158,41,26,0,208, +164,78,63,199,194,191,48,181,92,216,255,44,184,66,254,33,49,3,69,58,41,188,237,88,187,221,2,0,218,227,213,37,227,64,152,60,33,83,195,142,41,50,165,80,158,115,157,133,59,143,78,17,1,128,230,120,117,105,217,227,149,34,135,132,140,196,12,240,173,46,217, +2,219,43,76,0,16,111,252,164,143,179,206,70,48,32,33,35,49,3,92,99,11,108,175,48,1,64,52,47,244,111,44,252,11,83,232,82,221,79,184,243,26,22,222,45,132,245,244,58,6,59,31,218,42,0,104,135,181,244,60,156,135,163,229,1,66,11,239,65,90,244,9,214,99,11,236, +221,143,51,197,5,0,154,224,213,37,99,64,152,196,139,228,213,0,224,112,103,58,4,22,167,3,0,227,40,135,190,21,236,175,111,176,82,190,116,89,97,81,166,237,122,133,9,0,34,178,193,129,133,127,193,96,74,98,6,86,117,174,19,224,21,38,0,8,232,137,254,140,133, +127,193,96,202,214,179,176,166,60,219,195,19,34,137,99,0,136,200,174,147,22,254,5,131,169,228,105,52,232,140,212,219,105,0,0,234,229,193,148,133,127,225,40,231,201,52,54,224,112,118,27,208,54,1,64,84,94,93,178,240,47,28,45,210,194,156,166,177,193,244, +108,129,237,21,38,0,136,234,149,126,140,133,127,225,24,17,51,187,18,51,160,13,241,10,19,0,112,172,19,125,24,179,146,75,243,64,189,172,206,191,130,54,158,175,146,247,11,97,10,47,132,96,178,118,169,23,6,0,168,138,215,143,235,145,103,37,135,120,48,47,41, +163,33,169,69,151,54,175,92,72,204,192,225,206,183,117,137,105,252,36,4,0,224,222,205,44,242,184,239,165,241,31,165,233,147,105,108,127,40,6,112,240,141,205,78,3,211,30,127,42,86,0,80,85,95,72,255,197,194,191,197,49,83,166,190,164,76,116,121,10,155,5, +54,97,127,47,146,39,13,83,235,146,245,174,0,160,22,103,66,80,165,252,166,200,185,48,80,10,59,166,216,249,4,14,97,11,236,249,14,107,244,0,64,29,254,208,111,169,250,232,21,97,74,224,213,131,47,143,103,138,4,236,68,66,215,43,76,0,16,89,167,207,162,207,85, +42,175,47,213,213,144,120,245,224,75,249,9,245,153,48,192,157,242,148,207,94,24,102,109,155,59,97,0,128,226,251,67,212,223,231,58,111,241,196,36,101,234,97,221,130,155,189,212,200,194,157,188,94,163,163,7,0,209,253,75,8,154,240,127,169,193,135,97,146, +50,245,120,44,4,183,10,179,135,61,236,233,60,153,197,161,163,7,0,177,157,26,43,52,35,191,57,242,107,107,39,37,41,83,87,99,194,237,149,243,141,24,193,55,245,226,255,132,97,177,246,185,19,6,0,40,146,135,39,109,57,75,141,45,235,33,41,83,143,94,8,238,29, +128,190,73,214,221,129,43,182,192,94,150,87,152,0,192,61,154,101,52,181,225,139,164,76,29,204,0,217,141,196,12,124,110,51,206,132,97,81,63,9,1,0,20,217,39,234,132,161,57,77,205,126,146,148,169,167,49,97,247,88,73,204,16,157,197,125,151,215,107,119,0, +192,224,157,69,116,45,141,145,37,101,234,240,72,8,246,114,106,80,74,96,125,242,186,227,90,76,143,6,128,178,156,9,65,179,154,73,184,73,202,212,193,76,153,195,26,224,151,194,64,64,202,253,122,188,194,4,0,229,200,15,75,204,98,109,87,47,4,44,233,191,142, +131,143,115,197,135,64,158,169,243,171,31,58,127,0,80,134,151,250,37,250,93,53,48,83,166,124,102,201,28,39,239,99,127,38,12,4,112,178,45,239,172,171,23,2,0,40,130,215,138,141,149,171,32,41,163,160,69,144,179,228,103,194,64,227,114,66,198,44,141,245,121, +133,9,0,214,231,213,37,99,229,106,72,202,148,207,34,191,211,120,145,36,184,104,87,151,54,175,46,81,70,39,16,0,88,151,93,151,98,240,250,18,139,232,133,96,178,10,155,183,202,150,152,161,69,22,247,45,171,173,145,152,1,0,247,98,230,247,184,133,147,144,148, +41,159,36,194,180,13,244,155,100,42,35,109,233,147,228,109,105,188,194,4,0,235,145,144,161,42,146,50,229,15,182,152,150,196,12,173,49,75,70,103,16,0,248,204,195,17,170,34,41,83,54,179,100,230,139,171,196,12,45,200,235,200,116,194,80,156,19,237,55,0,172, +118,15,246,112,132,170,72,202,148,205,34,191,243,201,3,166,23,194,64,229,157,14,91,96,151,203,2,131,0,176,188,51,33,160,54,146,50,101,243,164,117,254,70,219,171,31,212,202,22,216,101,243,148,14,0,150,231,161,8,213,145,148,41,155,164,204,252,206,46,143, +115,97,160,50,93,178,5,118,13,215,72,27,14,0,238,189,204,231,67,11,39,33,41,83,174,94,8,22,147,103,28,156,9,3,21,49,195,171,14,158,214,1,192,114,204,82,141,231,125,11,39,33,41,83,46,89,222,229,7,185,103,194,64,5,250,36,105,91,211,181,2,0,150,225,97,72, +60,99,11,39,33,41,83,46,139,252,46,47,47,252,43,25,70,233,204,146,169,71,110,79,58,97,0,128,69,238,185,250,241,241,140,45,156,132,164,76,217,13,11,203,202,139,166,190,17,123,10,102,11,236,250,152,74,13,0,243,51,75,38,166,161,133,147,248,135,235,88,172, +255,10,193,106,242,130,81,255,76,141,44,28,69,51,114,210,240,207,100,199,165,218,188,187,60,126,16,6,0,152,85,238,35,117,194,16,202,112,121,252,216,194,137,152,41,83,166,94,8,86,31,252,190,49,248,165,48,182,192,174,147,87,152,0,192,189,150,233,253,222, +202,137,72,202,148,169,23,130,34,26,119,137,25,74,145,59,26,182,192,174,151,87,152,0,96,62,94,93,138,233,117,43,39,34,41,83,38,139,252,150,65,98,134,82,88,220,183,110,143,133,0,0,102,115,38,4,225,228,215,195,199,86,78,70,82,166,220,100,0,229,92,139,63, +92,19,86,212,39,179,231,106,151,103,202,72,238,2,128,123,236,156,222,5,58,215,127,183,116,50,146,50,229,201,141,74,39,12,69,201,215,35,207,152,57,19,10,86,240,66,8,154,233,52,2,0,211,250,73,8,62,185,184,60,126,78,49,54,42,201,231,248,186,165,19,146,148, +41,143,25,25,101,202,201,178,151,201,107,36,44,235,76,155,160,211,8,0,220,202,67,143,141,188,232,237,152,54,137,153,214,229,89,50,118,201,101,86,231,105,179,29,182,163,220,35,191,206,100,154,36,115,203,101,236,111,245,173,169,3,0,152,54,33,163,127,177, +233,47,94,247,172,241,115,109,110,28,102,166,76,121,44,242,91,190,60,115,225,207,100,157,15,230,245,44,73,254,181,216,121,4,0,166,97,215,165,141,175,95,229,249,45,109,94,103,106,209,47,201,44,25,22,144,7,251,50,190,245,28,182,41,102,14,157,186,213,228, +225,245,71,0,152,198,137,126,197,255,142,39,183,196,231,143,198,206,243,141,98,143,198,197,113,215,64,203,140,6,166,244,74,189,10,49,189,24,0,56,204,153,126,197,167,227,207,59,98,212,165,118,94,133,255,59,53,188,25,142,215,151,202,98,65,207,122,111,10, +111,92,63,38,210,39,175,185,180,234,196,181,5,128,73,88,64,127,227,174,93,136,198,212,206,194,191,79,183,231,3,179,59,79,178,189,181,103,112,13,184,56,214,27,117,201,43,76,0,192,173,188,93,240,249,216,229,161,112,237,11,255,190,80,228,49,24,115,236,123, +156,43,202,28,168,87,127,66,79,51,6,0,218,79,50,172,209,167,120,153,60,204,130,157,216,254,182,173,133,168,172,51,195,190,172,37,227,169,22,0,112,183,214,22,176,93,106,6,73,109,137,25,9,25,22,215,105,88,154,204,94,27,124,161,13,112,152,134,11,0,250,75, +83,31,221,1,241,171,37,49,19,42,33,99,161,223,114,24,188,183,121,211,200,153,252,51,161,96,7,214,35,114,173,1,0,247,208,93,188,75,135,45,124,155,23,204,253,165,240,115,123,190,253,158,97,72,202,148,67,82,166,93,47,147,233,119,220,207,46,2,113,116,218, +124,0,56,200,191,132,224,147,255,28,241,111,127,187,60,126,188,60,62,20,118,78,249,251,228,221,162,206,93,94,214,98,145,223,246,143,63,210,97,211,12,105,159,93,4,44,8,14,0,220,237,84,255,225,168,87,151,110,234,127,150,178,158,225,171,20,120,61,78,51, +101,202,106,100,104,255,26,231,196,76,47,20,124,69,153,136,199,204,40,0,216,143,89,50,27,135,190,186,244,181,171,153,41,63,78,244,243,14,49,110,191,195,207,169,188,153,59,139,145,148,41,67,151,236,212,19,69,190,206,121,86,212,51,161,224,26,73,217,152, +215,188,19,6,160,177,62,78,94,239,227,60,109,158,122,231,254,206,109,59,139,190,217,30,249,239,158,105,15,217,145,245,100,54,254,61,241,207,27,46,143,127,166,205,58,46,227,66,231,48,110,63,47,127,238,107,151,148,82,26,24,211,240,226,29,161,167,233,241, +5,91,97,199,60,36,103,129,218,229,100,74,222,81,110,138,45,138,243,174,149,47,13,188,185,133,87,151,62,31,115,143,31,158,204,216,55,125,165,142,83,170,115,141,75,232,117,102,204,146,224,15,117,33,108,253,7,168,209,217,204,247,174,63,183,253,99,15,175, +184,242,66,191,225,127,73,141,165,156,108,235,250,203,109,157,60,38,217,122,166,62,223,238,31,66,80,132,60,125,179,23,134,176,242,251,147,121,250,158,169,123,113,253,87,8,194,202,211,118,71,97,0,42,145,7,86,191,166,229,94,55,202,125,164,252,170,198,111, +41,240,122,19,124,242,183,65,253,39,121,204,112,177,210,103,231,248,159,110,143,171,107,241,232,218,239,223,94,171,183,87,235,222,232,227,236,64,82,70,35,67,57,114,135,227,23,97,8,73,82,70,231,10,160,100,125,218,60,237,238,86,250,252,60,200,123,190,237, +43,69,114,53,8,190,186,6,95,123,183,141,77,235,131,223,171,215,105,72,233,255,37,9,74,152,156,247,35,29,95,47,124,39,65,23,175,163,171,236,155,134,12,80,106,82,160,164,215,70,222,164,182,23,5,206,231,246,108,123,111,216,247,117,145,191,211,231,197,147, +91,123,53,254,165,254,194,167,227,165,38,9,230,113,166,129,113,164,111,223,189,180,206,140,164,140,195,130,125,0,107,202,125,145,18,215,60,251,123,219,127,110,41,241,245,108,134,88,255,185,77,168,181,144,196,250,91,95,225,211,97,129,92,152,137,69,171, +28,183,29,103,170,71,8,231,202,186,186,174,26,0,133,121,82,193,64,248,69,229,49,206,201,146,165,102,128,212,188,126,165,93,106,63,39,35,129,153,188,209,200,56,146,105,138,146,50,14,175,48,1,148,225,76,63,105,86,39,105,189,215,113,242,184,163,182,217, +216,175,146,126,130,49,1,204,76,35,227,216,101,219,220,78,85,105,150,206,134,195,66,207,128,132,76,140,193,106,126,77,169,132,25,72,47,82,29,175,206,158,232,31,120,117,9,230,102,145,95,199,62,83,22,123,85,166,73,102,203,57,116,182,128,18,212,252,154, +72,233,137,153,147,2,239,247,53,172,97,120,150,244,15,174,174,21,13,123,32,4,171,39,101,96,159,155,249,185,80,52,167,19,2,46,253,36,4,192,202,125,210,154,95,143,56,75,229,174,207,117,186,29,84,247,5,246,63,254,72,101,175,107,230,222,184,241,90,8,96,62, +22,249,117,28,186,254,132,221,90,218,225,245,60,175,112,89,192,15,88,123,112,222,202,238,54,165,61,240,60,171,36,110,47,10,45,151,250,253,101,150,107,38,246,157,16,172,74,5,227,16,79,182,55,170,167,151,199,59,225,168,190,35,28,221,47,219,56,68,127,125, +231,100,27,131,40,79,195,78,183,71,190,246,15,239,168,11,227,229,241,215,182,173,123,183,253,111,96,218,182,167,165,135,61,249,92,126,184,60,62,20,146,144,169,101,246,209,179,109,25,120,90,88,127,151,205,125,79,127,31,102,36,243,235,56,246,201,186,27, +86,221,250,100,214,215,213,160,64,157,174,127,123,215,251,6,126,103,219,107,254,247,145,237,222,203,237,207,50,99,16,142,215,226,186,102,37,180,165,103,201,218,60,199,250,67,191,160,249,190,1,172,206,34,191,142,169,142,51,213,169,90,79,130,151,221,174, +241,129,129,133,252,54,101,124,174,215,211,174,18,52,189,166,4,14,178,214,182,204,173,191,238,209,235,87,30,173,211,39,184,177,175,4,76,236,153,70,198,33,49,19,222,121,242,228,71,155,216,230,123,227,103,219,36,211,82,113,123,35,57,3,238,63,95,181,9,107, +37,19,90,88,159,103,237,246,84,159,224,243,186,123,192,140,94,106,104,28,18,51,225,189,80,94,191,232,200,170,199,245,79,83,238,211,186,83,206,223,36,79,21,97,151,164,105,132,246,116,141,196,66,43,175,220,228,196,210,154,175,136,254,153,244,7,254,187, +77,78,1,26,109,135,14,8,51,122,163,172,106,23,83,27,175,48,157,20,150,100,60,215,188,192,141,34,189,62,191,244,108,153,243,198,226,247,74,25,245,234,18,180,78,67,227,152,235,201,134,6,92,82,166,214,142,134,233,202,117,190,194,116,90,104,66,237,77,178, +24,48,124,93,87,91,217,250,186,180,135,85,93,163,241,91,99,67,137,200,179,136,189,186,4,11,234,53,52,14,141,56,193,203,105,164,78,109,203,211,149,207,10,31,228,253,157,218,89,167,7,142,113,146,98,206,70,92,106,182,76,171,15,89,214,152,189,233,213,37, +203,18,192,34,60,13,118,152,186,79,228,164,204,223,58,99,77,36,86,207,42,42,111,189,230,6,9,25,175,203,206,164,215,167,156,140,87,151,62,31,102,122,194,204,44,242,235,240,26,19,125,224,242,121,215,147,75,211,150,235,120,143,252,44,121,234,8,250,157,102, +203,164,212,254,171,200,127,43,171,97,214,243,97,37,15,132,96,21,166,82,51,183,156,93,255,85,24,40,212,135,59,254,236,63,194,243,201,147,130,191,219,217,182,227,92,155,23,238,191,4,244,34,73,72,246,105,190,217,50,115,254,236,146,250,148,75,149,161,39, +170,236,39,191,11,1,204,79,6,216,225,105,59,145,95,99,60,191,39,54,94,97,42,247,21,166,62,153,69,8,181,56,211,150,206,62,91,38,202,253,106,137,123,210,19,229,212,171,75,81,153,41,179,78,135,22,150,98,182,76,185,220,112,111,247,90,8,62,205,232,56,41,176, +204,190,106,160,222,189,82,255,8,32,15,112,95,10,195,23,253,239,169,251,224,103,41,78,146,247,116,129,115,253,73,49,253,228,34,221,61,163,152,6,73,202,172,211,168,193,82,34,117,24,106,243,48,240,185,15,247,252,185,105,187,159,7,85,37,105,37,153,145,239, +195,18,214,180,222,215,148,144,249,214,175,133,255,188,232,247,36,175,46,233,3,133,37,41,179,188,71,193,207,127,84,4,22,119,38,4,69,234,132,224,86,67,242,148,40,43,233,169,97,126,221,174,111,40,182,173,157,15,92,201,137,211,55,201,108,176,155,244,19, +214,251,179,128,247,241,57,239,73,103,202,236,39,185,239,99,182,48,44,32,250,90,9,209,183,101,92,227,248,83,181,211,22,164,250,222,149,182,3,67,57,239,149,231,239,240,183,182,17,170,72,200,232,99,205,191,182,204,73,224,123,248,92,94,41,155,159,14,51, +220,130,50,83,102,249,155,101,23,248,252,135,109,6,248,199,203,227,157,226,176,152,92,230,188,54,87,230,117,137,106,151,89,48,166,239,110,148,48,157,251,69,106,243,9,102,174,131,207,20,49,26,242,210,253,254,94,125,58,126,182,204,179,192,247,240,190,178, +159,91,27,125,159,160,36,101,150,21,253,70,249,238,218,128,44,39,102,46,20,137,234,111,162,28,230,68,59,112,175,215,201,43,76,217,218,175,48,229,129,199,89,195,241,253,53,153,50,79,27,114,66,198,154,28,187,215,251,99,238,223,255,103,44,51,121,31,85,59, +188,89,226,193,171,75,65,73,202,24,24,47,233,253,181,223,231,193,214,211,203,227,23,197,98,17,143,133,160,249,78,77,45,246,73,180,232,156,172,127,223,104,125,33,203,19,3,89,26,144,103,110,156,9,195,94,237,106,127,68,172,35,39,16,30,206,116,61,208,231, +9,77,82,102,89,209,23,249,189,233,9,249,111,105,51,107,198,19,241,182,7,118,124,59,16,140,106,220,227,239,190,85,84,86,77,26,68,73,88,216,137,137,154,157,165,205,43,134,204,95,239,163,207,146,201,230,120,168,244,72,113,252,228,63,66,16,151,164,76,253, +13,89,77,110,123,109,97,184,60,254,153,172,51,51,247,224,202,212,80,109,65,9,254,218,227,239,122,106,180,177,214,43,76,79,130,180,27,157,251,51,21,223,75,36,100,14,211,167,253,31,88,69,159,37,51,87,255,165,83,28,63,61,176,50,14,10,76,82,102,217,65,113, +228,70,103,184,231,207,243,76,153,31,146,117,102,36,2,136,208,241,216,149,173,33,55,214,154,173,242,83,160,24,255,159,98,70,133,247,116,91,95,31,103,159,217,50,93,50,171,238,106,60,115,50,67,89,142,78,95,39,56,73,25,3,226,165,236,154,253,125,186,61,188, +206,52,207,141,148,50,68,94,227,103,220,243,239,219,137,96,83,119,251,21,62,51,210,90,43,189,98,70,101,109,194,75,247,245,73,234,253,174,117,95,66,102,158,49,141,132,204,198,191,133,32,54,73,25,29,190,165,236,179,54,196,69,218,172,51,51,42,54,197,222, +68,225,80,251,38,92,61,61,218,88,122,214,74,180,123,86,167,141,164,34,111,148,215,201,236,146,108,201,237,195,153,80,205,210,159,236,132,243,211,131,107,99,158,224,36,101,150,99,145,223,253,255,126,126,157,105,80,116,38,243,189,16,52,217,161,105,189, +45,248,160,29,248,100,233,89,43,17,103,115,245,138,25,21,120,153,36,100,166,174,247,247,213,125,179,100,190,52,229,14,76,202,178,5,126,73,146,50,6,97,203,200,131,170,241,192,127,151,103,204,60,87,124,148,193,198,156,4,110,11,14,225,21,166,229,103,114, +68,108,47,236,0,66,233,206,147,25,27,115,248,245,158,182,80,204,231,187,63,104,119,205,8,38,73,202,44,217,153,238,2,159,255,177,171,137,231,78,200,207,201,58,51,18,1,58,51,81,219,2,29,150,141,127,45,248,89,125,208,123,53,148,42,39,6,204,216,152,175,189, +187,173,205,179,187,213,188,253,152,232,237,174,87,151,248,68,82,198,32,108,9,111,39,248,25,121,80,246,99,178,93,156,114,88,63,201,177,253,141,234,254,39,79,148,209,217,7,102,80,106,217,124,41,12,179,250,245,150,184,107,23,230,189,71,68,239,155,90,224, +151,79,36,101,12,134,151,240,110,194,159,147,19,51,23,138,148,193,86,197,186,192,231,126,76,130,214,59,215,203,205,186,148,192,133,178,250,144,175,132,97,118,125,250,54,1,99,102,210,221,241,114,175,57,158,153,192,124,34,41,179,140,199,193,207,127,202, +39,220,249,21,166,188,101,246,47,138,149,27,96,197,3,107,246,55,8,193,39,79,148,209,226,7,26,48,149,252,32,229,85,242,64,101,41,191,126,213,22,104,15,230,189,79,68,239,15,189,78,150,102,96,75,82,198,64,120,110,135,46,242,123,159,223,210,102,214,140,198, +140,218,60,12,124,238,239,142,252,183,163,226,179,200,186,50,145,59,202,6,191,148,84,22,223,24,184,46,170,79,159,19,49,214,146,153,255,62,17,253,65,161,77,12,248,31,73,153,101,26,173,200,157,188,57,215,129,24,46,143,127,38,107,77,236,219,225,160,254, +142,76,173,142,77,162,154,230,187,233,196,206,93,134,30,5,143,47,148,192,214,215,235,200,179,101,206,196,254,94,83,188,5,16,125,231,37,125,26,254,71,82,70,7,111,110,111,103,254,249,121,144,247,67,178,206,12,245,144,164,61,156,117,101,54,158,40,163,179, +121,168,120,81,128,151,105,185,133,189,249,82,159,204,146,217,69,87,200,207,168,213,69,50,219,159,107,36,101,230,103,145,223,101,60,221,30,26,184,187,61,22,2,109,194,138,142,173,159,94,97,218,248,105,129,65,137,129,6,172,227,108,123,176,30,175,49,46, +211,86,70,238,15,189,85,132,184,78,82,198,32,120,110,75,190,90,116,145,54,235,204,24,180,161,163,87,158,169,234,165,233,190,155,164,201,137,50,90,236,64,3,14,149,103,199,216,250,154,154,238,69,135,138,254,208,218,88,133,47,72,202,204,47,114,163,51,174, +208,232,228,36,208,15,6,110,179,220,64,209,30,148,208,1,241,116,233,243,224,77,25,157,94,167,104,177,226,253,65,66,134,40,237,101,244,182,118,80,124,184,78,82,102,254,198,202,250,17,203,203,175,72,252,124,121,60,87,4,161,24,227,68,63,199,22,146,27,115, +189,194,212,9,173,5,62,89,165,191,248,38,153,169,70,125,229,86,59,187,94,127,136,134,72,202,232,216,205,233,253,202,159,127,158,54,201,25,3,184,47,245,66,32,246,43,248,107,194,159,101,38,220,102,166,204,28,3,184,78,104,13,140,89,188,188,189,82,238,168, +208,49,75,52,68,222,121,105,84,116,248,154,164,76,185,141,85,11,134,2,190,67,30,188,229,215,153,108,155,13,235,154,50,57,250,187,112,126,50,199,43,76,118,31,242,64,133,101,189,82,230,168,212,49,137,196,46,112,220,188,134,205,55,36,101,116,236,230,84, +74,34,100,76,155,5,128,47,20,73,229,114,101,143,180,7,147,240,10,211,198,28,137,255,78,88,205,88,96,49,121,13,153,94,24,8,216,159,244,250,18,92,35,41,51,175,200,55,218,177,176,65,83,254,46,121,203,236,95,20,75,3,14,177,95,173,14,78,105,80,156,102,153, +41,35,105,107,150,43,203,56,79,182,190,166,126,167,11,253,155,214,198,72,240,5,73,153,178,26,169,150,148,250,186,208,111,105,243,58,83,228,167,236,143,84,79,237,66,3,109,130,87,152,54,73,190,39,51,252,76,113,101,74,253,229,241,44,109,102,133,228,197, +108,255,188,60,254,123,195,241,231,246,207,243,223,59,79,109,63,216,58,187,60,126,85,52,104,64,183,208,191,209,31,162,105,223,9,129,193,215,76,222,23,252,221,114,99,248,243,182,243,103,192,129,216,215,233,117,178,125,108,246,56,77,183,240,113,47,156, +238,223,19,181,115,57,89,248,83,218,47,105,216,125,53,88,251,245,90,93,207,107,48,92,164,54,30,168,216,250,154,214,218,203,215,7,252,155,168,62,36,175,95,115,3,51,101,230,19,125,54,194,80,248,247,139,156,165,54,224,88,71,167,61,152,188,99,99,23,166,105, +103,202,72,26,138,197,49,250,180,73,54,252,189,253,245,201,132,101,252,197,246,231,190,74,117,39,15,243,253,247,141,162,66,240,241,142,245,245,224,43,146,50,6,190,81,27,157,200,89,106,131,141,117,116,66,48,57,175,48,109,202,213,84,117,90,194,86,44,14, +209,167,77,162,33,31,103,51,127,214,147,107,159,213,87,120,239,181,245,53,250,54,177,251,67,146,50,220,72,82,102,222,78,74,84,99,170,35,233,97,182,12,165,119,92,116,66,238,102,166,204,180,245,217,118,216,234,235,62,114,114,225,106,157,152,165,251,60, +253,246,115,95,85,114,173,78,182,223,87,185,194,253,39,118,31,244,47,69,134,155,72,202,24,240,206,97,168,228,123,154,45,131,65,222,50,62,206,88,135,61,117,154,238,158,99,192,40,22,187,202,51,86,242,194,188,103,5,124,143,63,210,102,33,225,146,189,208, +55,196,61,200,24,73,159,133,219,72,202,148,221,65,174,213,251,74,190,103,228,134,209,128,99,121,223,235,132,204,226,63,138,150,215,151,102,96,214,208,237,101,45,207,142,41,233,53,156,252,61,94,164,114,95,13,58,75,182,190,70,159,82,255,211,216,131,59, +72,202,204,35,250,34,191,181,52,56,31,3,95,163,78,53,93,92,244,221,6,230,226,21,166,205,14,76,83,13,110,209,70,222,85,62,150,88,55,230,80,87,235,205,116,133,149,163,23,138,14,250,55,250,66,201,206,75,220,65,82,102,30,125,240,243,31,42,249,158,99,224, +107,228,41,240,58,3,154,168,198,153,127,118,244,39,79,83,12,66,205,146,17,143,251,226,241,166,130,184,228,239,247,71,65,223,243,101,146,236,164,125,143,102,250,187,173,49,75,134,91,73,202,232,204,69,110,112,198,192,215,169,83,77,181,11,13,213,181,232, +187,48,77,81,159,13,28,197,227,174,242,85,67,66,230,250,181,43,225,251,230,153,59,189,226,131,246,82,255,179,194,49,18,11,147,148,153,94,244,27,176,164,76,156,65,28,148,82,207,188,194,116,252,0,212,224,81,76,110,27,108,213,184,141,243,85,98,102,205,239, +237,181,37,180,149,211,223,171,106,102,231,37,110,37,41,83,94,199,184,118,239,43,250,174,99,224,235,212,169,170,6,119,13,213,179,119,193,235,115,154,96,240,249,189,106,202,13,106,154,33,115,83,157,88,43,49,115,230,62,139,126,165,190,231,13,125,21,184, +145,164,204,244,44,242,107,192,24,101,16,7,187,88,106,81,187,232,179,101,250,35,255,189,53,84,166,143,105,237,90,216,198,249,52,173,51,99,229,95,170,15,193,116,19,253,29,99,36,66,146,148,153,167,3,16,217,80,217,247,29,149,85,196,122,86,75,205,158,139, +190,53,246,177,139,119,119,170,233,55,34,207,30,234,47,143,103,141,156,203,89,218,172,239,178,100,123,223,171,62,4,108,51,166,248,59,173,178,243,18,119,146,148,49,248,154,82,141,25,224,49,240,245,50,83,70,172,151,234,136,44,213,254,68,174,207,221,202, +255,222,253,188,173,246,234,101,99,231,180,228,46,72,102,201,16,209,195,137,254,142,49,18,33,73,202,76,171,15,126,254,53,54,56,145,23,221,50,83,102,57,182,128,92,198,160,62,107,11,38,20,53,153,154,103,200,116,13,94,203,95,23,250,172,39,170,14,1,117,19, +253,29,125,33,66,146,148,49,200,157,210,251,10,191,115,228,169,132,22,246,52,184,107,205,239,202,152,242,233,158,126,244,192,234,215,70,207,109,137,100,83,151,204,58,35,166,126,162,191,211,42,59,47,113,39,73,153,105,69,95,228,119,168,240,59,71,206,92, +123,58,190,236,64,71,187,48,63,139,253,46,251,239,212,221,246,252,234,252,142,98,150,12,218,75,109,169,241,6,123,147,148,49,200,141,222,224,68,158,41,227,233,184,129,93,139,70,229,12,49,61,248,158,112,214,248,57,158,205,124,77,31,171,50,104,47,221,159, +26,25,35,177,32,73,153,105,69,78,202,12,26,73,229,21,29,145,2,234,215,168,172,25,72,106,39,15,242,44,200,121,254,223,140,63,187,87,101,8,172,87,55,110,100,231,37,238,37,41,227,70,92,243,224,107,202,198,18,74,27,40,183,210,17,209,22,45,231,208,87,104, +205,154,19,155,44,202,174,65,115,189,98,116,170,46,17,220,195,3,255,204,24,137,240,36,101,166,211,7,63,255,247,21,127,247,119,202,45,6,117,205,212,173,191,148,181,131,6,147,220,44,202,90,113,185,12,116,65,206,181,155,233,222,231,126,74,116,221,129,127, +166,47,68,120,146,50,58,110,26,28,51,101,152,127,176,19,213,71,109,209,162,14,25,20,118,170,232,157,162,36,85,163,45,80,251,211,12,63,211,107,128,232,239,76,123,127,106,133,157,151,184,151,164,140,129,151,129,80,221,179,124,214,24,196,177,159,200,91, +143,143,65,62,179,36,221,204,127,95,27,217,166,199,174,171,178,2,71,58,73,55,39,178,163,223,103,204,148,225,94,146,50,211,53,66,145,27,156,65,17,128,91,69,78,216,142,65,62,179,36,157,242,201,1,250,128,237,114,55,241,207,179,158,12,220,124,79,233,130, +199,68,82,134,123,73,202,24,116,105,108,98,39,149,76,183,102,78,163,54,169,248,251,145,129,228,253,122,231,231,188,197,16,14,190,7,69,174,31,118,94,98,39,146,50,110,198,83,120,175,8,128,246,225,6,99,176,207,45,193,190,73,22,137,217,233,99,90,155,46,232, +117,125,92,232,207,130,154,61,220,241,255,69,97,150,12,59,145,148,153,134,69,126,235,54,4,190,118,189,234,203,76,214,124,50,20,57,81,188,239,224,208,76,153,251,181,62,27,182,115,255,115,47,133,25,219,203,46,112,60,36,101,216,137,164,140,14,155,6,7,180, +13,173,181,11,99,224,184,119,202,232,228,90,127,202,251,56,112,93,153,162,252,91,79,6,238,190,167,244,129,227,97,231,37,118,34,41,115,60,139,252,58,143,22,111,160,76,215,62,68,181,230,76,153,49,112,220,59,229,115,213,152,106,167,234,210,23,242,51,160, +165,246,228,36,80,251,121,31,15,174,217,137,164,140,1,237,177,222,42,2,58,228,104,31,110,176,230,43,68,239,148,59,229,115,66,157,242,210,172,199,133,252,12,104,181,77,233,130,199,66,82,134,157,72,202,28,175,215,216,52,33,114,114,201,192,108,62,18,94, +235,136,190,219,193,174,229,174,83,84,194,199,41,122,251,223,23,242,51,160,213,118,37,114,253,176,243,18,59,147,148,57,94,244,39,36,50,192,113,6,112,236,47,242,142,3,131,182,169,248,129,102,167,138,30,52,200,104,73,244,50,112,114,228,181,237,221,67,225, +206,190,143,157,151,96,7,146,50,58,106,199,200,217,223,81,195,89,189,71,170,177,1,79,131,198,192,231,254,80,221,159,101,240,174,15,211,166,39,71,252,219,94,248,190,233,75,13,194,96,108,164,31,20,126,108,193,158,36,101,142,31,112,69,126,66,210,82,99,227, +85,7,230,106,35,180,15,235,248,75,185,83,247,103,26,100,180,228,161,75,123,212,140,103,235,201,124,217,143,250,241,242,120,46,20,250,62,215,126,223,7,142,131,157,151,216,153,164,140,78,218,49,90,90,135,229,157,114,204,138,131,227,86,59,232,234,116,217, +117,186,87,69,119,214,106,2,171,115,105,143,170,7,234,208,231,246,254,199,237,175,67,50,91,70,223,71,251,18,189,31,194,158,36,101,12,102,53,54,101,12,32,13,54,196,85,219,48,173,81,217,83,62,39,212,234,140,136,222,165,253,228,137,216,29,229,233,87,237, +190,217,50,228,250,209,5,143,193,168,24,176,43,73,25,157,180,218,7,94,206,103,26,157,234,60,185,232,235,77,169,207,101,15,182,205,144,219,79,139,73,44,237,254,113,253,185,94,216,62,201,9,153,215,95,253,191,33,153,45,19,93,167,142,72,202,176,59,73,25, +131,174,99,6,93,99,131,231,20,249,230,137,65,92,107,29,145,81,157,86,231,221,239,149,129,29,28,50,120,180,158,76,74,191,93,30,23,183,252,153,217,50,177,229,246,197,14,148,176,35,73,153,227,26,27,175,39,56,39,157,115,34,13,226,118,85,202,226,118,163,58, +173,206,79,168,181,123,190,217,82,95,198,98,223,235,219,7,143,89,158,29,243,203,61,131,82,3,211,184,30,7,191,207,140,138,0,251,144,148,209,153,57,212,219,6,207,233,163,1,28,52,213,25,177,213,253,237,236,186,227,190,175,12,124,105,159,117,101,122,225, +74,255,217,225,239,152,45,19,187,95,25,185,158,216,121,137,189,72,202,232,156,29,106,48,144,212,57,231,78,145,167,182,151,82,151,34,119,138,238,123,234,223,169,162,7,13,50,244,99,180,217,41,73,202,100,175,119,236,43,14,66,165,189,52,78,130,187,73,202, +24,112,29,170,197,39,208,99,224,235,105,128,198,148,74,89,159,41,242,76,153,251,6,141,6,228,218,73,101,96,191,58,163,15,120,216,128,211,108,25,34,26,133,128,125,72,202,232,204,28,218,208,124,104,244,188,12,54,208,70,28,239,157,58,93,124,189,182,37,246, +254,90,155,81,168,12,124,91,95,118,189,23,246,193,99,181,207,43,236,67,50,107,128,152,99,37,216,153,164,204,225,131,45,139,252,106,64,163,12,222,48,224,81,167,219,170,215,189,162,17,190,157,84,6,14,143,139,216,237,159,100,49,91,6,245,3,238,240,93,131, +131,160,187,158,78,231,100,194,20,51,60,162,79,249,125,223,248,32,174,11,122,93,79,82,236,109,193,167,20,185,141,40,173,51,242,46,240,245,56,189,229,122,72,24,170,215,157,203,121,163,159,210,237,91,60,95,233,133,105,239,118,126,216,30,98,71,4,163,16, +176,175,154,147,50,185,83,153,87,202,127,180,237,40,237,211,208,15,219,142,250,219,237,239,247,29,136,62,10,94,110,134,134,207,109,12,220,89,61,77,178,251,83,182,79,148,83,167,79,149,195,111,234,58,177,235,117,231,114,222,104,151,190,164,245,100,14,243, +60,73,202,16,131,157,151,216,91,109,175,47,229,14,209,217,229,241,230,242,248,251,242,120,121,121,60,59,160,145,239,183,255,238,213,246,231,188,218,254,220,93,59,92,209,59,180,45,47,158,57,26,112,96,192,115,148,183,133,125,159,247,129,175,197,109,131, +71,187,173,205,59,104,175,185,108,68,119,223,140,235,150,202,192,210,109,252,144,60,248,33,6,229,156,189,213,146,148,201,3,156,156,128,249,115,251,235,212,55,196,39,215,126,254,139,29,6,84,145,111,200,99,106,251,21,151,200,217,109,79,207,167,109,179, +40,167,205,82,14,149,79,190,36,9,127,88,31,239,137,240,28,53,224,180,182,12,250,29,112,131,210,147,50,185,211,112,149,44,57,91,160,19,145,127,254,179,237,231,157,223,242,121,102,201,180,45,242,154,42,223,107,18,39,19,121,38,66,105,109,68,228,206,81,119, +203,255,151,128,157,103,192,94,19,101,224,118,63,221,241,103,102,24,29,151,148,25,146,89,4,180,111,20,2,246,85,114,82,230,42,57,114,182,210,231,255,186,253,252,39,58,50,95,104,253,85,128,119,129,175,173,78,250,252,131,225,8,62,168,211,197,215,107,179, +36,14,247,125,163,101,130,207,250,3,255,44,130,97,130,159,97,182,12,234,8,124,165,196,164,76,238,44,230,53,99,94,20,208,113,204,159,255,106,123,92,125,23,139,252,26,80,182,202,64,77,44,167,240,174,192,58,173,94,27,144,79,229,180,193,50,193,183,250,91, +226,22,189,254,76,177,102,216,96,224,74,195,70,33,224,16,165,37,101,242,205,238,207,84,222,147,136,60,91,230,143,237,247,243,250,146,243,51,216,64,44,111,247,65,189,46,122,112,105,64,126,156,147,6,203,4,223,250,73,220,110,52,76,244,115,204,150,161,85, +118,94,226,32,37,37,101,206,210,38,241,81,106,135,167,219,126,191,200,55,229,119,41,198,19,231,15,154,6,56,200,232,123,21,231,161,129,229,164,78,27,44,19,124,235,166,122,98,61,153,233,146,50,67,50,91,6,117,4,254,167,148,164,204,89,218,44,232,75,217,222, +57,207,144,29,81,196,112,87,99,161,223,43,242,147,171,238,171,255,182,160,247,244,49,245,253,219,147,147,111,39,218,246,89,7,155,102,203,160,31,4,91,37,36,101,206,146,132,76,45,222,7,57,79,51,101,160,173,206,136,215,18,111,255,111,246,215,85,254,253, +123,151,112,239,56,89,79,102,154,245,100,174,27,146,89,5,232,7,193,39,107,39,101,242,90,45,18,50,245,136,50,176,121,31,248,26,235,172,139,225,49,74,157,145,18,185,147,244,245,211,254,78,21,61,218,105,67,229,129,219,61,214,174,127,97,152,225,103,154,45, +131,58,2,105,221,164,76,238,212,72,200,104,108,128,118,148,58,203,44,250,182,216,215,7,148,157,98,122,180,154,19,27,102,74,237,238,201,181,223,71,95,79,230,195,76,125,192,65,223,146,134,140,66,192,161,214,76,202,188,76,158,216,212,36,210,160,38,114,7, +193,66,134,199,123,164,157,208,89,42,76,103,64,174,142,43,3,7,213,155,171,186,211,7,143,197,156,253,34,179,101,104,133,157,151,56,216,90,73,153,23,58,6,6,91,208,40,201,230,50,141,193,7,151,202,166,58,158,217,121,105,63,125,178,158,76,246,118,198,159, +61,36,179,101,104,131,114,204,193,214,72,202,228,27,219,51,161,175,78,164,117,86,34,55,170,189,162,62,73,27,167,67,82,158,200,137,229,71,234,183,118,82,251,116,144,199,234,205,34,109,187,217,50,180,96,20,2,14,181,70,82,230,133,176,87,201,76,25,216,141, +217,8,101,250,75,153,68,76,173,41,180,167,188,174,140,245,100,230,239,3,14,201,44,3,234,55,10,1,135,90,58,41,147,111,110,189,176,87,105,112,190,97,120,146,106,192,211,98,157,137,156,88,190,186,239,90,51,74,59,217,185,116,123,201,201,183,51,253,191,69, +152,45,131,122,66,88,75,39,101,126,21,242,42,153,37,19,175,19,138,1,79,107,70,101,83,221,14,222,78,246,46,155,123,226,1,222,46,244,57,131,129,45,250,24,68,181,100,82,38,119,6,60,129,175,83,196,155,228,219,192,215,91,61,61,110,224,27,85,233,201,219,81, +217,84,183,131,183,147,157,203,70,225,125,64,179,101,168,149,157,151,56,202,146,73,153,127,9,119,181,222,11,65,40,158,166,27,244,28,226,99,5,223,49,242,172,191,159,84,207,73,213,184,139,81,231,178,177,167,37,214,147,185,110,72,102,203,80,39,229,150,163, +44,149,148,241,78,110,221,222,57,231,80,30,41,242,7,251,94,59,81,180,49,240,245,49,75,102,90,157,182,29,3,205,89,152,45,67,141,70,33,224,24,75,37,101,158,8,181,193,86,101,62,4,190,222,102,202,24,248,182,90,103,34,207,250,235,85,207,73,117,190,51,1,172, +241,42,247,144,204,58,160,62,163,16,112,140,165,146,50,166,77,215,43,234,141,49,242,76,25,79,212,105,181,67,162,211,196,84,58,109,59,250,128,179,49,91,6,245,132,80,150,74,202,244,66,93,173,168,201,9,51,101,208,214,237,103,244,29,9,230,212,119,165,241, +126,208,90,125,192,193,64,23,253,31,34,89,34,41,211,25,228,85,45,242,116,255,200,179,101,58,69,159,6,59,36,239,92,42,38,116,226,187,210,176,97,229,207,55,91,134,90,216,121,137,163,45,145,148,241,116,166,110,145,7,49,145,103,203,116,138,254,222,250,192, +231,62,86,84,167,63,40,170,4,172,243,189,203,197,158,222,174,252,249,67,50,91,134,58,40,167,28,77,82,134,251,188,115,238,33,117,138,62,123,248,160,94,67,209,30,10,1,21,14,52,205,150,65,31,136,16,150,72,202,124,47,204,110,200,149,250,24,248,220,59,197, +127,111,145,19,208,53,189,230,56,42,170,76,228,177,54,157,134,7,153,37,36,176,7,125,81,42,224,97,15,71,51,83,6,141,140,193,219,77,60,85,221,159,53,27,234,224,221,111,34,214,249,222,229,98,15,175,11,250,46,102,203,96,172,68,243,30,8,1,119,120,31,252,252, +199,192,231,222,41,254,123,123,20,248,220,7,29,40,2,170,229,161,147,132,49,251,122,91,208,119,25,146,217,50,24,43,208,56,73,25,90,25,104,105,104,167,213,41,254,6,62,234,53,52,81,239,205,88,166,246,254,223,47,46,9,133,122,47,4,76,65,82,134,219,124,48, +120,145,148,65,204,42,237,192,223,197,76,25,166,116,234,59,210,96,223,167,180,254,79,110,183,189,198,132,62,5,205,146,148,65,35,115,127,231,36,42,51,63,246,211,9,129,122,141,122,95,32,107,132,177,143,161,208,239,117,222,80,223,212,110,61,250,19,240,5, +73,25,110,243,86,8,194,55,182,158,174,182,53,48,155,203,59,245,26,117,95,91,142,254,223,2,158,166,250,19,26,249,251,255,168,152,233,3,193,117,75,36,101,12,238,53,50,53,139,60,120,51,83,166,173,129,217,156,29,76,237,27,81,213,176,192,119,231,50,177,135, +161,240,182,251,231,202,239,151,63,186,7,25,43,193,215,204,148,65,67,115,183,200,219,231,122,186,186,187,200,9,172,119,234,53,234,126,209,58,151,137,29,141,169,252,135,81,67,218,204,152,169,209,211,107,247,204,65,113,107,162,190,192,36,150,72,202,104, +116,234,99,145,223,47,99,17,213,247,46,255,206,34,39,176,62,86,248,157,37,157,137,82,247,123,151,136,6,251,236,23,169,190,196,76,254,190,175,13,232,155,98,231,37,38,243,157,206,47,174,153,88,84,58,216,160,12,163,239,76,96,39,190,31,13,169,105,201,129, +139,237,175,47,11,255,158,249,225,94,126,229,106,248,234,255,155,177,105,140,0,255,179,196,76,25,179,46,220,148,107,22,121,166,140,206,252,238,30,7,62,247,209,119,38,184,190,224,239,38,185,206,62,134,202,190,239,197,229,241,67,193,125,181,124,175,249, +241,150,184,14,138,155,254,15,92,89,106,77,25,13,79,93,100,126,197,66,103,158,214,59,37,218,57,34,120,36,4,236,209,150,215,216,158,231,182,252,159,5,142,53,242,171,74,63,220,113,175,177,45,182,49,2,252,207,82,73,153,223,133,90,35,83,49,55,78,238,211, +7,239,200,251,222,168,255,101,234,92,30,118,52,84,222,79,203,51,82,74,216,50,251,234,117,165,159,239,249,46,250,218,198,74,240,63,75,37,101,94,27,216,86,53,80,49,88,209,240,214,48,216,160,140,142,112,173,44,208,199,84,74,94,20,221,140,71,118,213,194, +171,235,23,105,51,107,230,183,149,238,135,207,183,159,255,90,255,50,196,120,9,38,179,228,150,216,175,133,187,10,110,16,109,13,60,49,232,209,94,232,80,17,179,13,232,92,26,246,48,52,212,103,251,37,125,78,206,124,88,224,243,174,146,49,231,123,126,158,251, +80,189,60,216,97,82,75,38,101,158,11,183,70,70,76,170,211,187,252,247,178,32,114,157,116,134,153,74,231,123,209,64,123,56,54,120,78,87,201,153,175,183,163,158,194,235,237,207,253,127,105,255,100,140,254,101,253,60,196,102,82,223,45,248,89,185,113,28, +12,242,138,55,8,1,236,37,242,76,153,154,167,187,235,80,49,149,174,208,239,165,191,133,190,223,38,89,114,177,61,78,182,245,226,241,246,222,221,239,241,51,222,109,143,183,219,120,77,49,3,199,125,168,94,163,16,48,165,239,22,254,188,231,58,9,6,42,149,118, +86,126,13,122,238,143,93,254,123,153,41,83,111,71,253,131,235,199,68,186,2,59,233,15,93,22,118,20,101,67,142,220,230,191,78,223,206,154,233,239,233,3,26,216,99,188,196,172,150,78,202,12,219,134,240,137,208,23,105,76,214,79,1,3,159,253,218,244,218,59, +85,189,34,204,4,186,2,7,88,157,203,66,144,182,188,214,243,55,176,175,183,239,0,147,122,176,194,103,254,98,224,175,145,113,179,174,134,1,171,129,79,203,70,33,96,34,167,190,19,21,247,253,244,203,245,189,209,119,96,69,15,86,42,200,22,253,45,147,5,199,96, +127,157,206,100,181,254,82,124,153,200,73,129,223,199,171,121,236,98,16,2,3,124,140,151,88,215,131,149,62,55,111,81,103,139,108,55,102,177,169,131,167,173,119,235,2,159,123,237,79,87,61,161,100,42,143,180,219,84,234,173,16,24,224,163,239,192,186,30,172, +248,217,121,27,185,209,37,208,200,80,60,79,91,197,166,213,246,194,61,136,86,219,2,73,25,118,53,8,129,123,41,250,14,172,107,205,164,76,126,194,250,115,242,30,107,73,13,140,107,113,187,200,79,146,116,238,197,230,182,54,92,103,24,54,250,194,190,143,100, +58,187,182,129,250,126,238,165,232,59,176,178,7,5,20,234,31,53,72,26,24,138,166,115,207,77,70,231,1,197,182,149,143,93,14,118,48,8,129,107,128,241,18,235,123,80,72,225,150,152,89,159,119,138,53,194,183,121,228,242,223,170,15,124,238,173,44,146,59,42, +198,76,164,164,153,115,157,203,129,190,159,251,16,174,21,117,120,80,200,247,144,152,41,227,26,112,187,200,101,211,76,25,90,238,152,104,251,104,177,173,236,92,14,118,48,8,129,251,41,123,177,48,51,179,120,80,208,119,201,29,227,127,234,32,187,49,27,184, +21,199,154,50,183,139,252,138,64,43,157,72,219,98,211,90,91,217,187,20,236,216,175,241,48,180,12,102,44,25,15,16,220,131,194,190,79,190,57,252,144,54,91,102,163,129,41,173,108,70,101,166,12,45,215,9,237,31,83,121,168,205,166,34,131,16,20,99,20,2,215, +138,216,30,20,250,189,126,73,155,45,179,101,240,13,74,196,169,12,157,203,127,163,83,245,65,7,11,10,107,39,205,110,100,23,102,103,184,15,97,44,64,33,30,20,252,221,46,210,102,157,25,133,127,126,222,143,220,77,228,36,97,231,242,223,200,19,105,157,97,40, +173,157,180,56,59,187,24,132,192,181,96,47,198,164,204,230,65,5,133,63,39,102,94,187,84,26,25,113,50,216,40,76,228,167,209,131,243,129,98,219,73,237,53,187,244,103,204,70,47,203,40,4,174,17,113,61,168,224,59,230,155,198,207,105,243,74,19,6,36,107,250, +104,176,193,53,102,201,180,195,224,132,169,156,250,14,232,247,97,192,223,36,111,22,48,155,7,21,125,215,188,248,175,109,179,167,103,150,140,27,230,46,30,186,252,223,232,2,159,123,107,107,17,232,104,49,149,181,147,181,157,75,64,192,54,220,53,193,56,128, +170,61,168,236,251,14,201,182,217,83,19,75,141,177,142,190,152,168,219,48,141,94,187,68,5,44,11,224,62,132,107,68,65,30,84,248,157,109,155,61,45,79,136,53,198,58,250,135,137,60,123,232,157,186,13,69,234,133,128,123,12,66,224,62,132,186,67,89,30,84,252, +221,109,155,173,129,113,195,92,78,231,242,139,201,53,173,181,187,218,65,166,242,120,229,207,247,170,41,247,241,154,76,153,204,92,55,6,32,176,7,149,127,255,139,100,219,108,55,1,141,242,82,44,108,43,30,45,183,27,18,252,180,208,46,116,46,1,247,24,132,160, +216,123,144,251,144,254,63,65,61,104,224,28,108,155,237,198,172,81,94,134,29,61,196,227,122,231,177,53,18,212,180,208,46,104,167,209,247,115,31,98,122,102,152,49,171,7,141,156,135,109,179,53,254,75,25,3,159,187,153,50,180,92,7,70,151,150,202,219,202, +19,237,52,247,24,132,64,191,28,125,4,202,243,160,177,243,177,109,246,126,44,242,187,191,191,2,159,187,39,176,159,245,58,38,234,54,20,214,86,106,163,185,143,167,253,238,67,232,251,80,160,7,13,158,211,144,54,219,102,15,46,239,189,100,228,247,23,57,225, +247,189,203,79,195,117,192,61,131,169,116,193,62,23,237,28,250,229,234,14,28,225,65,163,231,149,7,13,121,198,140,109,179,239,142,145,198,223,13,115,31,158,194,126,214,7,62,247,86,103,216,153,97,201,84,186,96,159,139,129,37,250,152,45,27,133,128,185,61, +104,252,252,242,26,51,63,235,108,187,49,27,184,77,194,90,5,180,92,7,116,134,153,202,163,149,62,247,177,208,163,223,87,253,253,213,152,165,60,163,16,48,183,7,1,206,49,239,202,100,219,236,111,253,46,4,6,110,123,50,83,102,253,65,151,58,160,227,69,249,214, +74,96,119,66,207,29,172,39,227,30,139,186,67,161,30,4,57,207,171,109,179,47,92,242,255,177,133,248,225,60,197,192,172,161,54,141,66,192,4,214,74,96,119,66,207,29,6,33,168,102,204,130,190,1,193,60,8,116,174,121,32,253,52,217,54,59,187,72,18,11,110,152, +135,233,93,254,85,7,93,58,246,243,242,52,140,41,172,145,180,53,147,145,200,109,119,75,236,192,84,158,81,8,152,219,131,128,231,156,23,255,253,33,197,78,74,252,71,209,63,138,132,22,102,202,168,219,112,151,126,225,207,235,132,156,59,12,66,80,13,51,101,212, +31,2,122,16,244,188,115,131,23,117,219,236,65,227,114,180,247,129,207,189,119,249,67,15,126,90,111,59,116,134,169,149,153,50,220,197,44,192,122,140,66,224,122,16,207,131,192,231,30,117,219,236,231,138,61,28,165,19,2,157,47,184,71,191,240,231,61,18,114, +238,48,8,129,251,16,174,7,229,122,32,4,161,182,205,30,220,152,117,110,142,100,203,213,216,175,46,181,62,147,68,231,139,169,124,175,93,162,16,31,244,253,244,51,57,152,89,102,44,66,82,102,35,194,182,217,87,11,29,3,199,137,252,154,192,71,157,97,40,178,157, +232,133,28,109,90,51,70,33,112,45,136,69,82,230,179,214,183,205,126,174,97,209,193,209,241,159,196,247,129,207,61,194,154,43,22,251,101,10,93,163,159,69,125,60,233,175,143,29,152,202,97,236,196,34,36,101,190,237,140,183,184,109,246,144,226,173,157,3, +115,137,60,83,38,66,194,226,189,34,206,4,186,70,63,139,58,251,128,184,102,184,22,20,76,82,230,102,45,109,155,61,166,205,154,57,104,164,167,98,151,143,184,70,231,8,59,235,22,250,156,94,168,185,69,238,199,218,85,206,125,8,215,129,194,73,202,220,174,133, +109,179,243,205,56,202,34,198,44,39,250,130,146,145,7,64,163,115,132,157,117,11,125,206,247,66,205,45,6,33,112,31,194,117,160,124,146,50,119,187,218,54,251,121,197,223,221,19,146,121,68,126,71,219,76,153,184,237,161,65,12,148,215,86,106,147,209,87,113, +47,66,253,161,98,146,50,187,57,79,117,205,56,145,144,97,78,145,103,202,244,129,207,61,82,123,98,118,33,53,181,149,146,50,24,216,183,103,20,2,215,128,56,36,101,118,151,183,205,254,161,130,129,137,132,140,1,234,220,30,185,252,33,125,80,191,97,47,143,23, +248,140,147,228,149,82,110,111,179,181,101,245,178,3,211,250,70,33,96,41,146,50,251,87,206,146,183,205,190,90,7,199,77,216,0,117,238,65,64,84,145,159,72,71,218,149,72,71,12,109,18,181,27,132,192,245,195,53,160,14,146,50,135,13,198,159,110,143,146,6,230, +121,221,155,86,118,140,170,65,228,196,87,228,65,128,39,210,49,120,66,201,20,250,5,62,163,19,102,110,97,61,140,250,199,27,172,103,20,2,150,36,41,115,184,139,180,73,130,188,46,32,57,144,191,199,185,75,226,102,185,144,200,137,137,200,175,110,13,206,21,138, +107,47,59,33,70,59,214,36,179,222,215,53,10,1,75,146,148,57,190,194,230,5,128,127,92,225,230,151,63,59,207,214,169,97,157,27,55,204,246,68,29,8,152,41,19,131,39,148,76,101,238,153,133,143,133,152,91,218,48,125,67,253,76,14,103,166,25,139,146,148,153, +198,144,54,137,153,124,204,61,115,38,55,208,57,25,147,215,142,185,16,122,3,183,149,116,206,59,100,59,167,35,12,251,49,83,6,237,53,135,26,133,64,236,137,65,82,102,250,155,96,158,57,147,19,38,191,76,120,83,204,13,195,111,105,51,43,38,31,23,66,109,224,182, +178,206,121,163,67,6,247,154,123,166,140,54,137,155,120,202,223,134,247,66,160,15,64,12,223,9,193,108,21,249,183,237,113,178,237,148,245,105,179,30,197,73,186,123,241,191,113,123,188,219,54,198,131,134,161,88,31,3,159,123,196,129,64,228,87,151,34,38, +32,71,3,94,38,240,112,198,159,109,231,37,110,51,8,129,123,47,234,16,245,144,148,153,223,135,109,197,86,185,219,28,180,25,104,196,17,121,0,20,241,85,189,252,164,185,215,204,113,164,174,210,159,77,221,237,181,193,188,126,38,226,78,69,188,190,4,26,109,131, +129,221,152,41,19,111,96,3,199,58,173,244,103,83,175,215,66,224,222,139,254,61,117,145,148,1,141,246,33,58,131,171,80,34,190,170,167,51,204,20,230,76,230,62,18,94,110,96,61,25,247,34,212,33,42,35,41,3,135,27,3,159,123,231,242,43,235,206,25,118,50,87, +66,247,68,104,185,193,32,4,238,69,28,197,76,89,22,39,41,3,110,150,6,4,187,121,172,156,59,103,40,168,173,236,133,150,27,218,45,109,87,91,236,192,180,60,179,147,88,156,164,12,24,184,29,202,122,6,113,68,125,106,52,184,244,76,160,159,225,103,118,194,138, +54,43,4,9,2,49,39,0,73,25,56,206,24,248,220,163,205,148,233,3,95,235,168,29,20,83,152,41,85,39,4,220,192,90,24,238,67,28,31,111,49,103,113,146,50,112,156,191,2,159,187,153,50,58,132,173,51,109,156,41,204,241,234,163,246,151,155,12,66,224,154,114,20,179, +100,88,133,164,12,24,176,30,234,251,64,231,26,121,0,20,185,131,50,106,226,152,192,28,179,10,31,10,43,55,180,87,218,44,247,34,244,121,168,144,164,12,104,188,15,21,41,81,97,151,19,29,97,40,169,173,52,83,134,175,13,66,224,94,196,209,254,18,2,214,32,41,3, +199,137,60,83,38,82,162,34,242,0,40,242,26,5,6,57,76,165,211,38,161,173,198,181,45,158,153,50,172,66,82,6,52,222,6,5,247,51,83,38,46,11,254,49,133,78,155,196,204,6,33,104,214,40,4,250,245,180,77,82,6,12,218,184,95,228,245,27,162,119,244,117,208,152,66, +55,225,207,234,133,147,27,6,237,6,238,109,95,95,150,233,207,235,211,179,10,73,25,48,104,51,56,88,118,64,133,206,48,241,116,133,254,44,218,48,8,129,235,139,254,60,245,146,148,129,227,201,170,183,47,242,171,2,209,59,41,22,253,99,10,143,38,252,89,157,112, +242,21,107,142,180,111,20,2,253,29,218,37,41,3,199,123,31,248,220,251,32,231,25,121,81,205,232,73,199,65,19,199,4,166,76,236,62,22,78,180,83,225,140,66,48,59,15,97,88,141,164,12,192,114,131,169,218,120,106,36,41,197,52,166,76,236,90,228,151,175,7,235, +6,236,237,51,27,74,159,135,134,73,202,192,241,134,192,231,30,225,137,173,89,50,58,105,112,172,41,19,41,182,195,70,31,36,158,81,8,220,239,105,151,164,12,0,58,129,226,192,252,250,9,126,134,132,12,95,251,93,8,220,135,56,154,157,151,88,149,164,12,28,111, +48,200,112,142,141,242,126,181,206,48,211,153,98,182,76,39,140,232,131,132,100,22,135,248,210,48,73,25,0,110,227,169,209,134,119,249,153,194,105,33,63,131,182,6,146,218,233,56,247,99,215,122,222,186,4,171,145,148,129,105,12,6,26,205,138,188,211,137,78, +202,231,206,48,28,235,251,9,126,198,67,97,68,223,195,61,153,201,153,25,204,170,36,101,128,99,217,9,164,93,146,17,58,194,76,103,138,4,118,39,140,92,99,22,159,123,17,98,75,3,36,101,64,199,168,132,129,134,243,211,73,41,217,40,4,76,160,155,224,103,244,194, +200,53,131,16,132,98,54,135,254,14,141,146,148,1,142,117,226,252,104,220,40,4,76,160,91,249,223,211,222,32,210,108,198,120,215,156,233,89,175,135,213,73,202,128,27,229,177,30,53,124,110,145,103,201,12,170,181,120,48,185,110,165,127,139,54,9,125,77,196, +149,66,73,202,192,52,34,103,216,79,156,27,234,56,236,164,59,226,223,218,121,137,235,172,39,19,243,62,228,94,52,61,73,25,86,39,41,3,26,244,99,181,60,80,232,2,95,87,29,254,47,189,23,2,86,110,47,237,188,196,117,131,16,232,111,50,9,107,245,176,58,73,25,152, +134,153,50,109,234,20,109,182,70,33,96,229,246,210,76,25,174,15,204,205,152,136,123,237,17,83,26,35,41,3,26,245,41,116,141,158,215,247,202,51,91,163,16,48,129,199,71,252,91,73,25,174,12,66,16,150,89,29,250,59,52,72,82,6,166,19,249,169,85,215,232,121, +157,42,207,24,4,81,8,107,92,113,197,235,165,113,73,32,76,223,215,209,223,97,117,146,50,224,70,57,133,206,32,72,121,14,210,121,131,99,244,11,255,59,218,52,8,65,88,163,16,232,235,208,30,73,25,152,206,199,192,231,222,53,122,94,102,202,160,243,198,212,14, +73,246,118,194,198,181,118,72,251,28,215,40,4,238,235,180,71,82,6,220,40,167,96,87,16,101,89,92,96,55,135,36,123,59,97,99,107,16,2,101,64,8,38,99,141,30,138,32,41,3,6,108,83,104,113,192,208,43,203,232,188,49,131,67,102,202,60,22,54,182,172,39,131,123, +244,116,204,148,161,8,146,50,224,38,57,133,206,229,111,138,169,241,55,27,132,128,9,28,50,83,198,34,191,92,121,45,4,225,121,64,48,29,73,25,138,32,41,3,211,25,3,159,123,215,224,57,245,129,175,231,123,213,249,70,146,85,76,225,144,215,61,109,135,77,54,8, +1,202,193,164,247,116,247,117,138,32,41,3,211,26,3,159,187,39,185,109,117,84,248,150,39,106,76,161,219,243,239,75,200,112,197,171,75,68,239,107,186,167,211,36,73,25,112,163,156,74,107,3,135,71,58,42,168,227,20,208,86,74,120,115,101,16,2,220,135,244,117, +104,143,164,12,184,81,78,229,196,249,160,142,195,228,109,75,47,100,108,13,66,128,178,48,153,143,66,64,41,36,101,96,90,145,23,95,59,117,62,58,123,1,120,125,128,165,219,151,135,194,133,118,153,175,140,66,160,78,209,14,73,25,152,86,228,181,56,190,111,236, +124,204,148,65,29,167,132,246,165,19,46,146,132,48,95,178,3,211,241,70,33,160,20,146,50,48,173,200,239,167,182,52,179,36,242,32,104,80,141,213,113,102,215,207,244,119,91,35,9,170,109,198,189,104,46,163,16,80,10,73,25,208,129,156,74,75,51,75,58,69,25, +157,56,180,171,171,27,20,1,177,192,189,72,125,162,117,146,50,48,45,51,101,12,132,148,97,29,97,184,207,227,128,237,234,33,158,43,42,6,144,184,87,187,151,211,58,73,25,152,158,233,214,245,139,60,16,178,27,129,1,18,243,219,53,241,27,185,45,26,183,3,79,131, +39,235,201,112,51,137,153,195,89,147,135,162,72,202,128,155,228,148,250,70,206,227,251,192,215,208,0,232,126,18,175,28,107,215,100,75,228,157,151,174,218,162,65,113,17,3,220,175,213,41,90,38,41,3,6,108,28,62,96,210,201,139,233,189,16,48,129,78,91,116, +167,171,7,28,102,137,24,64,226,94,164,175,67,211,36,101,192,77,114,74,189,203,175,163,34,70,176,147,110,162,191,211,170,171,215,11,134,224,229,100,80,85,184,133,215,151,220,199,105,132,164,12,192,183,122,29,21,196,136,153,117,19,253,157,214,7,156,99, +240,58,103,166,16,238,69,211,26,132,128,210,72,202,128,198,126,74,143,93,254,170,121,245,78,29,103,57,221,61,127,222,7,143,207,245,89,0,175,3,199,225,181,170,194,14,117,132,221,141,66,64,105,36,101,0,12,132,116,240,246,39,129,197,177,30,221,243,231,157, +58,246,63,111,3,199,64,187,140,251,246,180,236,188,68,113,36,101,96,122,67,224,115,239,93,254,102,6,65,232,8,51,175,251,182,197,238,220,71,195,223,87,7,213,132,123,140,66,160,94,81,63,73,25,128,47,69,222,237,196,78,14,58,194,148,211,214,60,82,191,254, +39,234,140,17,235,201,224,190,237,254,77,0,146,50,48,143,193,64,163,90,39,138,47,59,48,253,153,185,219,154,78,253,250,194,239,250,18,240,141,81,8,196,140,250,73,202,0,75,15,52,74,247,48,240,181,51,0,16,43,150,213,223,241,103,167,234,87,232,58,103,61, +25,118,49,10,129,123,55,245,147,148,129,121,68,158,114,92,251,64,162,83,124,217,113,192,4,199,58,105,180,29,157,163,126,13,193,234,157,93,151,216,197,32,4,123,25,133,128,18,73,202,0,75,13,50,106,209,233,220,177,3,79,176,153,194,105,163,237,232,92,245, +43,82,162,226,119,213,131,29,141,66,176,51,175,30,83,36,73,25,48,96,155,90,237,139,83,118,138,47,58,194,44,228,251,91,254,127,239,254,121,163,255,4,137,65,158,17,100,166,12,238,69,211,27,132,128,18,73,202,192,124,29,170,168,78,124,247,230,6,66,232,8, +51,143,219,102,202,68,94,219,234,195,61,3,170,8,245,238,223,170,6,123,176,75,151,251,54,149,147,148,1,3,220,165,6,25,190,123,189,3,33,116,132,153,71,183,231,255,87,175,82,122,30,32,6,23,170,6,123,24,133,64,172,168,155,164,12,24,224,78,205,76,25,29,21, +245,28,118,211,221,242,255,123,109,209,173,46,26,111,175,126,211,30,227,254,61,139,65,8,40,149,164,12,204,39,242,108,153,174,210,239,29,121,166,140,197,239,212,113,202,104,47,163,47,242,187,203,0,243,151,70,207,61,39,122,159,171,18,236,105,16,130,201, +218,22,88,133,164,12,204,219,185,50,200,64,103,69,204,96,159,246,50,250,118,216,187,12,48,95,55,58,16,125,158,204,192,195,253,104,46,30,62,81,44,73,25,152,143,153,50,245,121,172,67,135,152,177,176,211,123,254,59,146,125,18,18,79,83,91,9,140,33,109,94, +93,2,247,163,249,234,24,20,73,82,6,230,243,49,240,185,119,46,127,211,131,33,116,242,152,206,215,175,43,69,222,121,105,159,135,25,121,16,218,202,107,76,185,253,125,170,42,112,4,11,207,239,214,102,64,145,36,101,64,227,63,135,90,7,21,189,193,16,7,12,166, +224,24,95,207,208,139,60,83,102,223,118,232,34,181,177,83,209,83,3,70,220,139,244,203,137,75,82,6,52,254,115,232,92,126,157,185,32,222,11,1,218,207,201,28,178,230,67,78,104,212,156,84,206,235,200,188,86,236,57,146,7,43,119,27,132,128,146,73,202,192,124, +70,131,138,170,120,58,141,122,206,26,250,6,218,207,181,219,162,31,43,109,199,46,46,143,115,85,0,247,113,247,106,98,147,148,1,55,128,57,212,56,168,56,81,100,81,207,89,185,253,233,213,167,131,228,217,126,181,37,102,46,146,117,100,152,206,135,100,214,235, +93,236,188,68,209,36,101,192,128,109,238,65,70,45,186,192,215,202,2,129,135,27,132,128,9,156,86,218,110,150,116,207,188,74,204,212,80,39,243,43,75,18,50,76,205,108,25,247,106,42,37,41,3,229,118,48,91,25,100,212,162,83,92,57,98,48,8,83,180,63,145,95,163, +28,38,170,139,57,49,83,234,214,210,87,187,44,157,43,242,204,64,82,70,127,156,74,73,202,128,155,192,92,106,123,226,27,121,27,218,65,85,213,17,102,85,221,246,215,71,238,151,147,200,91,101,255,156,202,74,152,230,118,34,39,140,46,20,119,102,226,21,29,253, +113,42,37,41,3,110,144,115,49,83,6,157,61,216,205,67,237,208,228,247,203,188,163,209,63,211,250,59,27,229,196,80,126,93,233,135,36,129,203,188,148,175,155,13,66,64,233,36,101,96,254,206,88,84,223,87,246,125,35,175,229,160,35,87,214,96,146,120,186,237, +175,118,129,155,254,30,156,103,204,172,181,214,204,69,218,36,99,206,21,113,220,203,87,51,10,1,165,147,148,1,55,200,185,156,250,190,213,176,38,202,113,6,33,96,130,246,167,51,112,154,181,142,254,152,150,73,206,228,246,244,34,109,102,233,60,53,32,100,225, +123,185,251,249,183,60,56,161,120,146,50,96,176,59,151,19,223,53,252,64,72,61,135,221,219,160,46,120,12,150,120,136,49,164,77,98,38,39,76,158,79,252,153,249,53,169,167,73,50,134,246,235,145,152,192,196,190,19,2,112,35,152,201,169,239,90,5,3,7,245,156, +50,252,159,58,180,104,187,119,190,61,186,203,163,79,155,69,150,79,183,191,191,207,135,237,119,126,187,253,117,72,146,179,148,83,151,122,97,208,207,161,46,146,50,48,191,220,81,59,17,6,116,86,154,143,99,39,12,28,193,43,148,235,213,221,139,91,174,199,201, +13,127,87,155,73,201,62,10,193,55,60,56,161,120,146,50,176,204,205,160,15,122,238,249,188,135,74,190,103,84,222,181,158,110,96,215,9,3,71,136,92,126,222,26,200,193,36,114,159,235,87,97,80,143,169,139,53,101,96,126,166,52,163,124,26,84,178,155,81,8,92, +119,64,93,18,15,34,145,148,129,249,189,15,124,238,125,37,223,243,113,224,107,228,41,210,52,36,183,166,49,8,129,129,19,160,46,233,131,19,137,164,12,64,108,146,9,211,144,220,154,198,239,66,16,210,32,4,160,62,185,55,19,149,164,12,184,57,206,169,150,25,40, +145,23,216,212,97,153,198,40,4,202,35,7,145,24,6,247,35,177,32,52,73,25,0,187,99,161,227,87,130,65,28,67,146,136,131,105,89,192,95,251,66,101,36,101,96,153,129,70,84,125,5,223,177,83,54,17,79,157,104,92,111,112,47,210,182,192,26,36,101,128,232,58,33, +96,34,94,195,56,206,91,113,12,201,83,125,152,214,40,4,226,64,93,36,101,96,25,67,224,115,47,125,189,150,206,32,152,137,216,229,225,56,87,201,24,79,55,99,113,189,97,90,163,16,184,39,83,23,73,25,96,110,165,175,215,210,185,68,232,8,23,53,56,255,40,20,234, +13,112,148,65,8,36,124,169,135,164,12,44,35,242,140,132,210,103,202,124,175,195,130,193,101,81,241,51,152,80,111,0,245,74,12,8,67,82,6,152,91,233,51,101,34,111,135,109,237,142,105,13,66,48,73,7,90,185,84,103,128,227,88,171,201,131,39,42,34,41,3,110,12, +115,123,84,248,247,139,188,29,246,168,106,78,78,66,225,248,54,82,71,90,125,1,244,59,157,63,97,72,202,128,142,231,220,204,148,41,215,168,106,234,8,22,218,70,26,172,199,96,33,78,112,127,119,254,132,39,41,3,6,106,115,59,117,249,117,88,196,149,123,188,213, +102,186,55,2,234,214,68,36,124,169,138,164,12,44,195,76,153,50,245,129,175,203,168,90,206,194,123,252,211,180,145,202,167,118,8,56,206,59,231,14,117,144,148,1,55,136,37,116,46,127,241,131,96,166,49,8,193,36,237,163,228,150,251,34,112,156,209,185,67,29, +36,101,192,32,120,9,93,161,223,171,15,124,77,76,237,85,207,75,238,64,235,80,27,52,1,238,243,135,146,240,165,42,146,50,224,6,177,132,206,229,47,142,228,129,122,94,242,0,221,128,61,222,53,7,220,143,156,55,33,73,202,192,114,62,6,62,247,174,208,239,245,40, +240,53,209,105,49,216,44,57,94,202,103,251,222,10,1,184,23,57,111,144,148,1,55,137,101,60,44,244,123,157,40,150,168,235,69,198,203,76,46,245,4,56,78,212,228,182,215,179,169,142,164,12,232,128,46,161,243,189,138,51,168,146,179,49,3,96,154,129,131,50,234, +158,8,204,211,190,58,103,40,136,164,12,232,128,46,161,243,189,8,196,44,143,253,124,20,2,131,69,96,22,131,115,134,242,73,202,192,114,198,192,231,222,249,78,6,67,226,203,158,29,104,51,142,218,245,33,73,94,194,18,162,181,163,239,180,45,212,72,82,6,150,53, +6,62,247,210,214,111,233,130,15,136,80,207,75,47,143,202,105,219,3,39,96,126,67,176,243,253,221,37,167,70,146,50,96,176,182,148,211,194,190,79,228,69,126,13,136,212,243,26,202,163,114,170,13,2,142,147,147,219,23,129,206,247,194,37,167,70,146,50,96,176, +182,148,210,146,32,167,129,175,133,53,60,230,55,8,193,209,109,162,153,50,218,32,224,120,81,102,143,188,75,30,138,80,41,73,25,88,214,95,129,207,189,180,36,200,247,6,194,204,72,66,225,248,178,104,54,69,187,6,33,128,197,188,14,114,223,255,183,75,77,173, +36,101,192,64,109,41,165,37,65,34,207,148,25,85,197,217,189,23,130,157,188,83,86,181,65,192,236,158,7,104,83,46,92,102,106,37,41,3,101,13,64,90,118,234,242,27,16,137,49,95,249,40,142,234,7,48,187,139,198,235,221,115,151,152,154,73,202,192,178,34,207, +148,41,109,77,153,222,128,8,49,94,221,187,35,255,156,250,12,66,0,171,104,53,113,145,239,183,23,46,47,53,147,148,129,178,6,32,45,51,83,166,12,214,58,49,240,172,169,60,90,16,86,27,4,76,227,162,209,123,211,83,151,150,218,73,202,128,14,105,68,125,224,115, +55,243,64,93,47,201,160,188,134,99,189,37,88,207,211,198,238,77,191,37,15,65,104,128,164,12,24,20,47,169,119,249,87,39,81,160,174,215,84,22,149,87,245,2,152,206,120,121,252,210,80,91,98,45,25,154,32,41,3,6,197,17,69,126,149,202,83,234,101,59,191,28,55, +56,31,132,73,189,0,38,117,145,234,95,131,37,247,165,91,155,245,67,96,146,50,96,80,188,164,190,144,239,113,162,24,178,128,191,132,192,224,156,111,152,41,3,235,203,9,141,161,226,239,255,179,182,132,150,72,202,0,17,61,12,124,238,131,203,47,214,133,248,75, +28,195,25,133,0,138,81,107,98,163,246,132,18,124,67,82,6,12,212,150,244,184,144,239,209,41,134,44,192,180,234,187,189,19,199,112,70,33,128,162,238,81,63,166,186,18,51,57,33,115,225,210,209,26,73,25,32,162,206,64,24,177,46,98,64,176,11,235,32,181,227, +173,16,64,113,237,112,78,204,188,174,224,123,230,153,61,23,46,25,45,146,148,129,229,13,129,207,189,47,228,123,116,6,194,44,100,20,130,163,219,66,49,84,31,128,121,251,5,57,225,81,234,78,70,249,1,71,13,137,35,56,152,164,12,16,77,228,69,126,205,220,48,8, +21,67,92,75,224,38,231,105,147,252,40,169,158,254,150,234,123,197,10,246,38,41,3,235,24,2,159,251,105,240,207,95,147,89,50,203,243,186,198,241,109,160,129,124,59,12,172,160,252,182,249,135,180,73,134,172,41,183,251,57,25,243,139,190,11,17,72,202,0,75, +59,9,254,249,107,119,114,88,150,206,228,241,113,81,110,219,185,230,234,3,212,81,87,115,50,228,159,105,249,135,136,107,126,54,172,70,82,6,214,17,249,105,161,153,50,235,249,75,213,83,215,11,241,94,28,213,5,160,104,99,218,204,86,201,51,103,46,22,248,172, +188,179,82,78,198,252,38,244,68,35,41,3,235,248,24,248,220,79,92,254,85,59,88,136,121,141,113,49,195,66,93,0,214,145,19,170,57,97,242,255,182,191,78,181,224,110,110,19,114,2,38,39,125,114,50,230,66,91,79,84,223,9,1,172,118,131,139,234,209,202,159,255, +216,160,8,49,175,46,46,185,205,236,133,173,106,102,234,65,221,114,194,228,34,125,158,53,211,111,143,220,175,59,185,167,141,30,183,71,110,203,243,76,201,193,253,17,62,147,148,129,245,110,108,81,153,41,163,220,69,51,36,9,133,175,237,155,152,254,40,100, +77,212,3,160,173,58,173,94,195,4,188,190,4,117,12,72,90,98,77,25,229,46,26,201,176,227,99,162,227,95,191,81,8,0,224,91,146,50,96,144,182,52,187,47,41,115,209,188,23,130,47,12,202,111,72,163,16,0,192,183,36,101,96,61,145,103,45,116,43,125,174,89,50,24, +140,174,239,131,242,171,253,1,0,54,36,101,160,174,129,73,43,186,149,62,215,122,54,172,97,20,130,47,28,58,115,200,108,25,117,0,0,154,35,41,3,58,169,107,232,130,125,110,9,222,170,114,171,25,132,224,11,135,38,87,204,182,168,151,87,248,0,224,22,146,50,176, +158,200,219,131,118,193,62,23,204,242,248,236,208,228,202,40,116,225,174,57,0,52,79,82,6,214,19,121,128,241,48,216,231,26,20,33,254,199,183,125,127,9,93,181,36,37,1,224,22,146,50,80,223,192,164,5,93,176,207,53,40,98,20,130,163,99,33,177,85,175,65,8,0, +224,102,146,50,96,144,182,134,110,165,207,141,188,208,175,1,237,186,204,242,56,190,28,74,44,186,215,1,64,115,36,101,64,71,117,13,221,74,159,27,121,75,108,3,218,117,13,66,112,116,57,148,88,116,175,3,128,230,72,202,128,206,234,90,78,26,255,60,229,140,235, +36,197,54,222,138,161,107,14,0,124,38,41,3,6,203,107,57,109,252,243,148,51,174,51,203,99,227,216,196,202,32,132,225,174,57,0,52,77,82,6,116,86,215,114,226,242,47,102,20,2,215,161,16,146,83,174,57,0,112,141,164,12,172,235,125,224,115,95,122,230,74,31, +56,214,22,153,45,195,40,4,71,199,192,171,48,245,145,148,1,128,59,72,202,192,186,34,207,148,249,126,161,207,233,46,143,39,151,199,99,229,140,149,73,40,28,159,148,81,150,235,107,123,92,51,0,184,195,119,66,0,171,138,252,4,241,116,166,159,153,143,71,215, +126,239,53,41,79,170,75,26,160,70,54,42,203,218,30,0,224,75,146,50,96,144,182,150,99,147,37,125,250,156,128,233,82,236,215,147,148,51,3,212,26,140,133,252,12,234,186,230,0,208,52,73,25,48,72,91,203,174,51,101,78,182,127,183,79,159,19,48,167,138,142,114, +102,128,26,178,28,26,228,215,197,122,86,0,112,15,73,25,88,95,158,197,224,21,155,207,174,18,48,143,183,191,239,132,132,70,140,193,207,255,227,132,113,212,46,212,97,16,2,0,184,155,164,12,172,47,63,61,238,131,158,123,191,29,96,229,95,115,18,38,47,200,43, +65,101,80,212,250,245,232,149,197,163,228,54,163,83,148,170,48,10,1,0,220,77,82,6,88,211,171,36,9,67,44,31,156,251,209,34,39,178,107,51,10,1,0,220,205,150,216,176,190,200,219,228,74,200,204,207,122,50,101,121,175,44,30,237,163,98,164,237,1,128,86,72, +202,0,180,205,0,182,44,163,243,54,216,119,205,1,128,43,146,50,176,190,65,8,152,145,1,172,129,106,107,231,109,139,247,58,188,23,2,0,184,159,164,12,64,219,12,96,203,50,4,61,239,119,98,232,154,3,0,223,146,148,1,131,52,218,54,10,129,107,82,128,191,38,254, +121,146,141,229,115,141,0,96,7,146,50,0,18,0,44,107,112,206,71,51,11,67,57,7,128,38,72,202,128,206,43,237,26,133,160,72,209,118,92,203,51,38,222,205,240,51,209,246,0,64,245,36,101,0,12,140,88,214,16,236,124,95,207,240,51,45,34,171,237,1,128,38,72,202, +64,25,76,197,103,14,102,19,148,59,96,141,84,231,127,55,232,119,79,3,0,110,38,41,3,101,248,40,4,204,192,108,130,114,253,39,200,121,230,196,224,28,51,101,70,69,168,104,127,9,1,0,236,70,82,6,202,224,169,34,115,13,136,41,211,69,144,235,115,49,211,207,29, +21,33,247,52,0,104,129,164,12,24,60,99,96,196,58,117,254,117,128,243,252,247,76,63,119,84,132,180,61,0,208,2,73,25,208,129,5,214,241,188,241,243,187,72,243,38,79,180,155,101,202,215,220,131,6,0,216,145,164,12,148,65,7,150,57,12,66,80,252,224,245,183, +134,207,111,238,164,147,118,83,187,3,0,213,147,148,129,114,120,234,11,241,228,196,197,135,70,207,107,156,249,51,222,42,62,69,114,93,0,96,15,146,50,80,14,79,125,153,146,36,95,61,245,254,105,99,231,52,166,101,102,0,141,138,79,145,94,11,1,0,236,78,82,6, +202,26,200,192,148,131,125,234,25,196,182,52,144,253,121,161,242,55,40,58,69,150,101,109,15,0,236,65,82,6,202,241,151,16,48,33,51,101,234,146,103,203,140,13,156,199,47,11,150,189,49,73,102,151,230,63,66,0,0,251,145,148,129,114,24,92,48,165,143,66,80, +149,60,187,96,169,25,38,115,185,72,203,47,92,236,85,153,178,238,97,174,7,0,236,73,82,6,202,234,208,130,242,20,87,158,97,242,99,170,51,49,147,191,251,26,107,227,152,153,81,142,231,66,0,0,251,147,148,1,131,104,148,39,202,145,147,27,249,21,160,15,149,125, +231,31,87,252,108,101,189,140,246,230,66,24,0,96,127,146,50,96,16,141,242,68,89,242,224,182,150,25,51,175,11,248,174,255,86,100,86,247,139,16,0,0,208,130,63,47,143,255,58,28,19,28,212,239,180,240,54,225,69,33,113,58,185,60,254,86,231,87,59,94,169,170, +0,112,56,51,101,160,44,163,16,48,1,91,210,182,33,191,154,243,67,42,111,241,212,171,69,137,127,41,232,251,152,45,179,94,236,159,10,3,0,28,78,82,6,12,166,105,115,48,79,59,109,194,207,169,156,157,153,134,84,102,162,232,55,237,231,42,158,138,59,0,28,71,82, +6,202,242,94,8,152,192,40,4,205,201,73,144,127,166,229,183,156,190,94,166,114,98,232,199,66,203,87,78,12,88,215,100,89,207,147,45,176,1,0,104,204,179,100,125,2,199,241,199,51,85,169,105,221,229,241,50,45,179,142,74,94,211,230,172,162,216,188,81,255,23, +57,94,170,134,0,0,180,168,215,217,119,76,112,156,170,74,33,228,5,110,115,2,238,143,137,203,207,223,219,65,119,95,105,194,202,162,191,18,50,0,80,141,127,8,1,20,229,116,59,192,130,67,229,215,56,254,159,48,132,147,147,17,79,46,143,199,219,118,164,219,243, +223,15,105,179,22,209,219,84,255,43,41,57,14,118,4,154,199,69,178,176,47,0,76,74,82,6,202,99,59,99,12,154,56,86,158,69,115,53,99,170,191,225,207,199,237,145,147,120,45,46,12,125,150,204,232,152,90,94,207,200,186,61,0,0,52,207,212,123,199,49,199,19,85, +8,62,121,169,61,152,236,117,54,237,10,0,0,97,88,168,210,113,204,162,172,128,196,204,84,71,190,31,117,138,17,0,204,199,150,216,0,237,248,143,16,192,23,242,171,124,94,185,217,223,135,109,236,74,221,2,29,0,0,102,115,158,60,157,117,28,246,138,193,137,234, +3,55,122,146,188,26,186,107,59,114,174,45,1,128,229,152,41,3,208,134,127,167,205,211,109,224,91,121,71,169,60,235,227,157,80,220,40,199,37,207,140,201,59,183,157,107,75,0,0,136,172,79,158,214,58,204,146,129,185,156,39,179,102,174,214,139,121,150,172, +25,3,0,171,250,78,8,0,170,247,60,121,178,13,187,58,79,155,173,227,127,77,155,173,179,91,117,125,187,243,241,242,248,43,125,222,10,125,80,12,0,160,12,255,16,2,40,210,127,133,128,29,229,193,213,143,194,0,7,233,210,38,57,147,215,156,41,125,182,217,245,36, +75,254,253,251,91,254,191,87,180,0,160,34,146,50,80,38,73,25,118,29,164,253,144,236,142,2,199,202,9,153,156,152,249,87,218,188,66,186,148,225,218,239,223,222,242,255,7,151,7,0,218,37,41,3,101,122,179,240,192,128,58,253,156,54,11,152,2,211,57,217,182, +191,143,47,143,211,237,177,235,44,154,60,75,229,234,85,66,73,22,0,224,94,146,50,80,38,73,25,238,243,203,229,241,155,48,192,98,110,75,206,92,79,196,0,0,0,13,120,145,236,12,226,184,253,120,169,138,0,0,64,253,30,8,1,20,233,163,16,112,139,139,203,227,169, +48,0,0,64,253,36,101,160,76,118,207,224,38,249,149,37,9,25,0,0,104,196,119,66,0,69,146,148,225,186,188,94,69,78,198,88,212,23,0,0,26,98,161,95,40,215,223,105,247,29,63,104,87,78,208,229,93,150,70,161,0,0,128,182,120,125,9,202,53,8,65,104,121,118,76,126, +93,233,135,36,33,3,0,0,77,146,148,129,114,189,21,130,176,46,46,143,127,38,91,94,3,0,0,192,42,186,100,235,231,72,71,126,93,237,197,246,186,3,0,0,0,43,123,35,89,209,252,241,234,242,56,83,212,1,0,32,30,187,47,65,217,254,115,121,244,194,208,140,49,109,22, +238,125,159,54,107,6,13,66,2,0,0,113,217,125,9,202,247,103,242,74,75,141,222,109,143,191,210,38,249,146,127,255,65,88,0,0,128,43,102,202,64,249,242,108,153,95,133,161,104,67,250,156,128,121,151,204,128,1,0,0,118,96,166,12,148,239,228,242,248,35,153,45, +83,130,60,211,37,39,93,242,206,88,99,250,60,27,6,0,0,96,111,146,50,80,135,179,203,227,165,48,44,106,76,95,174,255,50,110,15,0,0,128,73,72,202,64,61,242,78,76,189,48,204,226,106,198,203,251,107,191,183,254,11,0,0,48,43,73,25,168,71,151,54,175,49,157,8, +197,81,134,244,57,1,51,38,235,191,0,0,0,43,145,148,129,186,156,37,175,49,237,234,250,250,47,249,215,49,89,255,5,0,0,0,56,194,139,203,227,191,142,111,142,63,182,177,121,146,204,38,2,0,0,0,102,146,103,203,68,79,194,252,185,141,195,89,146,132,1,0,0,0,22, +20,45,49,243,119,250,156,132,233,92,126,0,0,0,96,77,45,39,102,114,18,230,213,229,241,236,242,56,117,169,1,0,0,128,210,180,180,198,76,222,246,251,60,217,250,27,0,0,0,168,196,89,218,204,44,169,117,113,222,222,37,4,0,0,0,106,213,165,205,76,19,59,36,1,0, +0,0,172,224,44,149,51,107,230,250,14,73,157,75,3,0,0,0,180,46,207,66,57,79,203,39,103,174,47,206,219,185,12,0,0,0,64,84,57,57,115,150,54,175,13,205,149,136,177,67,18,0,0,0,192,29,186,180,73,158,28,187,238,140,29,146,0,0,0,38,240,15,33,128,176,250,180, +73,212,228,227,97,186,249,117,163,15,151,199,251,203,99,220,30,131,176,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +176,175,255,47,192,0,205,180,140,11,223,168,97,120,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::noise_wave_png = (const char*) temp_9db0b117; + +//================== saw_wave.png ================== +static const unsigned char temp_c4474a8[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,4,180,0,0,2,143,8,6,0,0,0,116,54,147,247,0,0,0,9,112,72,89,115,0,0,23,18,0,0,23,18,1,103,159,210,82,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101, +97,100,121,113,201,101,60,0,0,41,190,73,68,65,84,120,218,236,221,141,149,212,102,186,174,225,103,38,129,211,206,64,206,0,71,176,69,6,56,130,45,34,216,16,1,69,4,248,68,208,58,17,152,12,90,19,1,236,8,80,6,144,129,143,100,53,174,6,131,145,212,245,163,159, +235,90,235,93,94,158,25,51,174,183,170,87,21,55,42,125,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,151,242, +47,43,88,180,155,110,158,116,83,222,255,253,127,125,231,127,247,159,251,191,54,221,188,239,230,147,213,1,0,0,0,112,41,207,186,185,237,230,67,55,127,204,156,15,247,191,198,51,235,4,0,0,0,224,28,250,171,176,250,0,245,49,243,35,214,247,230,227,253,175,253, +196,154,1,0,0,0,120,172,178,155,187,156,62,98,125,111,238,114,252,250,34,0,0,0,0,140,86,228,178,33,75,216,2,0,0,0,96,182,67,174,23,178,132,45,0,0,0,0,70,235,79,44,188,230,85,89,63,10,91,110,32,15,0,0,0,192,95,250,27,178,159,227,134,239,167,158,254,116, +196,202,211,5,0,0,0,176,111,253,149,79,107,136,89,194,22,0,0,0,0,127,70,161,63,86,60,194,22,0,0,0,192,142,244,95,51,252,99,35,35,108,1,0,0,0,108,220,90,238,153,37,108,1,0,0,0,240,231,105,134,239,178,189,152,245,117,216,122,113,255,88,1,0,0,0,88,185,55, +217,118,204,122,56,253,85,104,135,8,91,0,0,0,0,171,85,102,63,49,75,216,2,0,0,0,88,185,62,230,244,95,197,251,99,199,35,108,1,0,0,0,172,200,33,251,142,89,194,22,0,0,0,192,138,244,225,102,139,167,26,10,91,0,0,0,0,27,117,136,120,245,163,176,117,219,77,225, +165,2,0,0,0,176,12,123,191,119,214,148,17,182,0,0,0,0,174,236,89,68,42,97,11,0,0,0,96,69,250,48,35,80,9,91,0,0,0,0,171,225,102,240,194,22,0,0,0,192,106,148,17,162,206,17,182,158,120,105,1,0,0,0,223,243,111,43,120,148,210,10,78,174,234,230,93,55,119,246, +11,0,0,0,112,122,125,116,113,85,213,121,71,216,2,0,0,0,56,161,15,17,156,132,45,0,0,0,128,21,17,154,132,45,0,0,0,128,213,40,34,46,9,91,0,0,0,0,43,82,70,84,90,74,216,170,188,28,1,0,0,96,63,156,114,200,218,149,221,220,102,184,159,89,101,29,0,0,0,176,125, +130,22,91,81,68,216,2,0,0,128,93,16,180,216,154,34,194,22,0,0,0,108,154,160,197,86,21,17,182,0,0,0,96,147,4,45,182,174,136,176,5,0,0,0,155,34,104,177,23,69,134,176,245,177,155,67,55,55,86,2,0,0,0,235,36,104,177,55,125,200,122,149,225,138,173,67,132,45, +0,0,0,88,29,65,139,189,18,182,0,0,0,96,165,4,45,246,78,216,2,0,0,128,149,17,180,96,32,108,1,0,0,192,74,8,90,240,165,175,195,86,97,37,0,0,0,176,44,130,22,124,219,195,176,213,159,142,88,88,9,0,0,0,44,131,160,5,63,86,69,216,2,0,0,128,197,16,180,96,188,42, +194,22,0,0,0,92,157,160,5,211,85,17,182,0,0,0,224,106,4,45,152,175,138,176,5,0,0,0,23,39,104,193,227,85,57,134,173,210,58,0,0,0,224,188,4,45,56,157,170,155,187,251,41,173,3,0,0,0,206,67,208,130,211,43,35,108,1,0,0,192,217,8,90,112,62,101,132,45,0,0,0, +56,57,65,11,206,175,140,176,5,0,0,0,39,35,104,193,229,148,17,182,0,0,0,224,209,4,45,184,188,50,67,212,234,79,70,172,172,3,0,0,0,166,17,180,224,122,138,110,110,35,108,1,0,0,192,36,130,22,92,95,17,97,11,0,0,0,70,19,180,96,57,138,8,91,0,0,0,240,67,130,22, +44,79,17,97,11,0,0,0,190,75,208,130,229,42,242,101,216,186,177,18,0,0,0,16,180,96,13,138,28,195,214,33,194,22,0,0,0,59,39,104,193,122,244,33,235,85,132,45,0,0,0,118,78,208,130,245,17,182,0,0,0,216,53,65,11,214,75,216,2,0,0,96,151,4,45,88,63,97,11,0,0, +128,93,17,180,96,59,30,134,173,55,25,110,38,15,0,0,0,155,35,104,193,246,244,97,235,69,134,176,213,159,142,88,88,9,0,0,0,91,34,104,193,182,85,17,182,0,0,0,216,24,65,11,246,161,138,176,5,0,0,192,70,8,90,176,47,85,132,45,0,0,0,86,78,208,130,125,170,34,108, +1,0,0,176,82,130,22,236,91,149,33,108,221,117,83,90,7,0,0,0,107,32,104,1,189,50,67,212,18,182,0,0,0,88,60,65,11,120,168,140,176,5,0,0,192,194,9,90,192,183,148,17,182,0,0,0,88,40,65,11,248,39,101,132,45,0,0,0,22,70,208,2,198,40,115,12,91,207,172,3,0,0, +128,107,18,180,128,41,202,110,126,207,112,50,98,101,29,0,0,0,92,131,160,5,204,81,116,115,27,97,11,0,0,128,43,16,180,128,199,40,34,108,1,0,0,112,97,130,22,112,10,69,132,45,0,0,0,46,68,208,2,78,169,136,176,5,0,0,192,153,9,90,192,57,20,57,134,173,67,55, +55,86,2,0,0,192,169,8,90,204,209,90,1,35,21,221,188,138,176,5,0,0,192,9,9,90,204,241,188,155,167,221,52,86,193,72,125,200,18,182,0,0,0,56,9,65,139,185,154,12,81,75,216,98,10,97,11,0,0,128,71,19,180,120,172,38,67,212,250,165,155,218,58,24,73,216,2,0,0, +96,54,65,139,83,121,159,225,171,136,63,71,216,98,60,97,11,0,0,128,201,4,45,78,173,141,176,197,116,159,195,214,199,12,167,35,22,86,2,0,0,192,247,8,90,156,75,27,97,139,121,170,12,87,108,9,91,0,0,0,124,147,160,197,185,181,17,182,152,167,138,176,5,0,0,192, +55,8,90,92,74,27,97,139,121,170,8,91,0,0,0,60,32,104,113,105,109,134,176,245,83,55,175,187,249,100,37,140,84,69,216,2,0,0,32,130,22,215,211,135,172,67,134,43,182,132,45,166,168,114,12,91,79,172,3,0,0,96,127,4,45,174,77,216,98,174,170,155,119,221,220, +117,83,90,7,0,0,192,126,8,90,44,133,176,197,92,101,134,168,37,108,1,0,0,236,132,160,197,210,8,91,204,85,70,216,2,0,0,216,5,65,139,165,122,24,182,94,102,184,153,60,140,81,70,216,2,0,0,216,52,65,139,165,235,195,214,111,25,194,86,127,58,98,107,37,140,84, +70,216,2,0,0,216,36,65,139,53,169,35,108,49,93,153,33,106,245,55,144,175,172,3,0,0,96,253,4,45,214,168,142,176,197,116,79,186,185,237,230,67,132,45,0,0,128,85,19,180,88,179,58,194,22,211,21,17,182,0,0,0,86,77,208,98,11,234,8,91,76,87,68,216,2,0,0,88, +37,65,139,45,169,51,132,173,95,187,105,172,131,145,138,8,91,0,0,0,171,34,104,177,69,111,187,121,122,63,141,117,48,82,17,97,11,0,0,96,21,4,45,182,172,137,176,197,116,69,134,176,245,177,155,67,55,55,86,2,0,0,176,44,130,22,123,208,68,216,98,186,62,100,189, +202,112,197,214,33,194,22,0,0,192,98,8,90,236,73,19,97,139,233,132,45,0,0,128,133,17,180,216,163,38,194,22,211,9,91,0,0,0,11,33,104,177,103,77,134,168,213,159,140,88,91,7,35,9,91,0,0,0,87,38,104,65,210,118,243,60,194,22,211,124,29,182,10,43,1,0,0,184, +12,65,11,142,218,8,91,76,247,48,108,245,167,35,22,86,2,0,0,112,94,130,22,252,93,27,97,139,121,170,8,91,0,0,0,103,39,104,193,247,181,17,182,152,167,138,176,5,0,0,112,54,130,22,252,88,155,99,216,250,173,155,79,86,194,72,85,132,45,0,0,128,147,19,180,96, +188,182,155,151,25,194,214,235,8,91,140,87,69,216,2,0,0,56,25,65,11,166,235,67,214,33,194,22,211,85,25,194,214,239,221,148,214,1,0,0,48,143,160,5,243,9,91,204,245,172,155,187,251,41,173,3,0,0,96,26,65,11,30,79,216,98,174,50,194,22,0,0,192,100,130,22, +156,142,176,197,92,101,132,45,0,0,128,209,4,45,56,189,135,97,171,63,29,177,181,18,70,42,35,108,1,0,0,252,144,160,5,231,211,135,173,58,194,22,211,149,17,182,0,0,0,190,75,208,130,203,168,35,108,49,93,153,33,106,245,39,35,86,214,1,0,0,48,16,180,224,178, +234,8,91,76,87,116,115,27,97,11,0,0,224,79,130,22,92,71,29,97,139,233,138,8,91,0,0,0,130,22,92,89,157,99,216,122,111,29,140,84,68,216,2,0,0,118,76,208,130,101,168,187,249,165,155,167,221,52,214,193,72,69,132,45,0,0,96,135,4,45,88,150,38,67,212,18,182, +152,162,200,151,97,235,198,74,0,0,128,45,19,180,96,153,154,8,91,76,87,228,24,182,14,17,182,0,0,128,141,18,180,96,217,154,8,91,76,215,135,172,87,17,182,0,0,128,141,18,180,96,29,154,8,91,76,39,108,1,0,0,155,36,104,193,186,52,57,134,173,218,58,24,73,216, +2,0,0,54,69,208,130,117,106,186,121,222,205,207,17,182,24,79,216,2,0,0,54,65,208,130,117,107,35,108,49,221,195,176,213,223,68,190,176,18,0,0,96,77,4,45,216,134,54,194,22,211,245,97,171,138,176,5,0,0,172,140,160,5,219,210,70,216,98,158,42,194,22,0,0,176, +18,130,22,108,83,27,97,139,121,170,8,91,0,0,192,194,9,90,176,109,109,142,97,235,117,55,159,172,132,145,170,8,91,0,0,192,66,9,90,176,15,109,134,83,237,132,45,166,170,34,108,1,0,0,11,35,104,193,190,244,33,235,16,97,139,233,170,12,97,235,174,155,210,58, +0,0,128,107,18,180,96,159,132,45,230,42,51,68,45,97,11,0,0,184,26,65,11,246,77,216,98,174,50,194,22,0,0,112,37,130,22,208,251,58,108,181,86,194,72,101,132,45,0,0,224,194,4,45,224,161,135,97,171,63,29,177,181,18,70,42,35,108,1,0,0,23,34,104,1,223,83,71, +216,98,186,50,199,176,85,89,7,0,0,112,14,130,22,240,35,117,132,45,166,43,187,185,205,112,50,98,101,29,0,0,192,41,9,90,192,88,117,132,45,166,43,34,108,1,0,0,39,38,104,1,83,213,17,182,152,174,136,176,5,0,0,156,136,160,5,204,85,231,24,182,26,235,96,164, +34,194,22,0,0,240,72,130,22,240,88,117,55,79,239,167,177,14,70,42,34,108,1,0,0,51,9,90,192,169,52,17,182,152,174,200,49,108,29,186,185,177,18,0,0,224,71,4,45,224,212,154,8,91,76,87,116,243,42,194,22,0,0,48,130,160,5,156,75,19,97,139,233,250,144,37,108, +1,0,0,255,72,208,2,206,173,137,176,197,116,194,22,0,0,240,93,130,22,112,41,77,134,168,245,75,134,27,201,195,24,194,22,0,0,240,55,130,22,112,105,239,187,121,222,205,207,17,182,24,79,216,2,0,0,254,34,104,1,215,210,70,216,98,186,207,97,235,99,134,211,17, +11,43,1,0,128,253,17,180,128,107,107,35,108,49,79,149,225,138,45,97,11,0,0,118,70,208,2,150,162,141,176,197,60,85,132,45,0,0,216,21,65,11,88,154,54,95,134,173,79,86,194,72,85,132,45,0,0,216,5,65,11,88,170,54,199,176,245,58,194,22,227,85,17,182,0,0,96, +211,4,45,96,233,250,144,117,136,176,197,116,85,142,97,171,180,14,0,0,216,14,65,11,88,11,97,139,185,170,110,238,238,167,180,14,0,0,88,63,65,11,88,27,97,139,185,202,8,91,0,0,176,9,130,22,176,86,194,22,115,149,17,182,0,0,96,213,4,45,96,237,30,134,173,151, +25,110,38,15,99,148,17,182,0,0,96,149,4,45,96,43,250,176,245,91,134,176,213,159,142,216,90,9,35,149,17,182,0,0,96,85,4,45,96,139,234,8,91,76,87,102,136,90,239,50,220,72,30,0,0,88,40,65,11,216,178,58,194,22,211,61,233,230,182,155,15,17,182,0,0,96,145, +4,45,96,15,234,8,91,76,87,68,216,2,0,128,69,18,180,128,61,169,35,108,49,93,17,97,11,0,0,22,69,208,2,246,168,206,16,182,158,118,211,88,7,35,21,17,182,0,0,96,17,4,45,96,207,154,12,81,75,216,98,138,34,194,22,0,0,92,149,160,5,32,108,49,79,145,33,108,125, +236,230,208,205,141,149,0,0,192,101,8,90,0,71,77,132,45,166,235,67,214,171,12,87,108,29,34,108,1,0,192,217,9,90,0,127,215,68,216,98,58,97,11,0,0,46,68,208,2,248,190,38,199,176,245,214,58,24,73,216,2,0,128,51,19,180,0,126,172,233,230,215,12,39,35,214, +214,193,72,194,22,0,0,156,137,160,5,48,94,219,205,243,8,91,76,243,48,108,189,201,112,51,121,0,0,224,17,4,45,128,233,218,8,91,76,215,135,173,23,25,194,86,127,58,98,97,37,0,0,48,143,160,5,48,95,27,97,139,121,170,8,91,0,0,48,155,160,5,240,120,109,132,45, +230,169,34,108,1,0,192,100,130,22,192,233,180,57,134,173,223,186,249,100,37,140,84,69,216,2,0,128,209,4,45,128,211,107,187,121,153,33,108,189,142,176,197,120,85,132,45,0,0,248,33,65,11,224,124,250,144,117,136,176,197,116,85,134,176,245,123,55,165,117, +0,0,192,151,4,45,128,243,19,182,152,235,89,55,119,247,83,90,7,0,0,12,4,45,128,203,17,182,152,171,140,176,5,0,0,127,17,180,0,46,79,216,98,174,50,194,22,0,0,8,90,0,87,244,57,108,253,148,225,116,196,214,74,24,169,140,176,5,0,192,142,9,90,0,203,80,103,184, +98,75,216,98,138,50,199,176,245,204,58,0,0,216,11,65,11,96,89,234,8,91,76,87,102,56,17,177,63,25,177,178,14,0,0,182,78,208,2,88,166,58,194,22,211,21,221,220,70,216,2,0,96,227,4,45,128,101,171,35,108,49,93,17,97,11,0,128,13,19,180,0,214,161,206,49,108, +189,183,14,70,42,34,108,1,0,176,65,130,22,192,186,212,221,252,210,205,211,110,26,235,96,164,34,194,22,0,0,27,34,104,1,172,83,147,33,106,9,91,76,81,228,24,182,94,116,115,99,37,0,0,172,145,160,5,176,110,77,132,45,166,43,186,121,147,33,108,29,34,108,1,0, +176,50,130,22,192,54,52,17,182,152,174,15,89,175,34,108,1,0,176,50,130,22,192,182,52,17,182,152,78,216,2,0,96,85,4,45,128,109,106,114,12,91,181,117,48,146,176,5,0,192,42,8,90,0,219,214,116,243,188,155,159,35,108,49,158,176,5,0,192,162,9,90,0,251,208, +70,216,98,186,135,97,171,63,29,177,176,18,0,0,150,64,208,2,216,151,54,194,22,211,245,97,171,138,176,5,0,192,66,8,90,0,251,212,70,216,98,158,42,194,22,0,0,87,38,104,1,236,91,27,97,139,121,170,8,91,0,0,92,137,160,5,64,175,205,16,182,126,234,230,117,55, +159,172,132,145,170,8,91,0,0,92,152,160,5,192,67,125,200,58,100,184,98,75,216,98,138,42,199,176,245,196,58,0,0,56,39,65,11,128,111,17,182,152,171,234,230,93,55,119,221,148,214,1,0,192,57,8,90,0,252,19,97,139,185,202,12,81,75,216,2,0,224,228,4,45,0,198, +16,182,152,171,140,176,5,0,192,137,9,90,0,76,241,117,216,106,173,132,145,202,8,91,0,0,156,136,160,5,192,28,15,195,86,127,58,98,107,37,140,84,70,216,2,0,224,145,4,45,0,30,171,142,176,197,116,101,142,97,171,178,14,0,0,166,16,180,0,56,149,58,194,22,211, +149,221,220,118,243,33,194,22,0,0,35,9,90,0,156,90,29,97,139,233,138,8,91,0,0,140,36,104,1,112,46,117,132,45,166,43,34,108,1,0,240,3,130,22,0,231,86,103,8,91,191,118,211,88,7,35,21,17,182,0,0,248,14,65,11,128,75,121,219,205,211,251,105,172,131,145,138, +8,91,0,0,124,69,208,2,224,210,154,8,91,76,87,228,24,182,14,221,220,88,9,0,192,126,9,90,0,92,75,19,97,139,233,138,110,94,69,216,2,0,216,53,65,11,128,107,107,34,108,49,93,31,178,132,45,0,128,157,18,180,0,88,138,38,194,22,211,9,91,0,0,59,36,104,1,176,52, +77,134,168,213,159,140,88,91,7,35,9,91,0,0,59,34,104,1,176,84,109,55,207,35,108,49,205,215,97,171,176,18,0,128,237,17,180,0,88,186,54,194,22,211,61,12,91,253,233,136,133,149,0,0,108,135,160,5,192,90,180,17,182,152,167,138,176,5,0,176,41,130,22,0,107, +211,70,216,98,158,42,194,22,0,192,38,8,90,0,172,85,155,47,195,214,39,43,97,164,42,194,22,0,192,170,9,90,0,172,93,155,99,216,122,29,97,139,241,170,8,91,0,0,171,36,104,1,176,21,125,200,58,68,216,98,186,42,199,176,85,90,7,0,192,242,9,90,0,108,141,176,197, +92,85,55,119,247,83,90,7,0,192,114,9,90,0,108,149,176,197,92,101,132,45,0,128,69,19,180,0,216,58,97,139,185,202,8,91,0,0,139,36,104,1,176,23,15,195,86,127,19,249,214,74,24,169,140,176,5,0,176,40,130,22,0,123,211,135,173,58,194,22,211,149,17,182,0,0,22, +65,208,2,96,207,234,8,91,76,87,102,136,90,253,201,136,149,117,0,0,92,158,160,5,0,194,22,243,20,221,220,70,216,2,0,184,56,65,11,0,142,234,8,91,76,87,68,216,2,0,184,40,65,11,0,254,174,142,176,197,116,69,132,45,0,128,139,16,180,0,224,251,234,12,97,235,105, +55,141,117,48,82,17,97,11,0,224,172,4,45,0,248,177,38,67,212,18,182,152,162,200,151,97,235,198,74,0,0,78,67,208,2,128,241,154,8,91,76,87,228,24,182,14,17,182,0,0,30,77,208,2,128,233,154,8,91,76,215,135,172,87,17,182,0,0,30,77,208,2,128,249,154,8,91,76, +39,108,1,0,60,146,160,5,0,143,215,228,24,182,222,90,7,35,9,91,0,0,51,9,90,0,112,58,77,55,191,102,56,25,177,182,14,70,18,182,0,0,38,18,180,0,224,244,218,110,158,71,216,98,154,135,97,235,77,134,155,201,3,0,240,13,130,22,0,156,79,27,97,139,233,250,176,245, +34,67,216,234,79,71,44,172,4,0,224,75,130,22,0,156,95,27,97,139,121,170,8,91,0,0,127,35,104,1,192,229,180,17,182,152,167,138,176,5,0,240,23,65,11,0,46,175,205,49,108,189,238,230,147,149,48,82,21,97,11,0,32,255,178,130,217,202,110,238,118,250,216,251, +99,233,27,47,1,128,147,249,124,207,164,255,137,19,238,152,166,206,16,69,91,171,0,128,85,127,22,124,242,157,255,238,125,252,225,39,39,86,118,243,199,78,167,244,244,3,156,237,195,204,161,155,143,59,126,143,49,243,230,206,251,51,0,172,66,145,225,15,50,251, +171,173,223,77,124,175,239,255,153,42,174,210,230,145,202,8,90,0,156,135,176,101,132,45,0,216,142,162,155,55,25,110,27,112,170,247,252,62,134,189,136,184,197,12,101,4,45,0,206,75,216,50,194,22,0,172,187,27,220,93,224,125,255,119,239,251,76,125,97,10, +90,0,92,130,176,101,132,45,0,88,87,47,184,68,200,250,214,251,254,19,235,103,204,11,84,208,2,224,210,170,156,246,114,117,35,108,1,0,167,209,255,33,228,239,11,120,223,127,19,7,13,33,104,9,90,0,11,85,69,216,50,243,194,214,51,63,62,0,112,114,253,251,235, +146,174,166,255,224,247,238,8,90,130,22,128,176,101,182,54,31,238,95,59,0,192,227,189,89,240,123,254,193,211,131,160,37,104,1,8,91,70,216,2,0,62,91,202,87,12,127,52,183,158,42,4,45,65,11,64,216,50,194,22,0,208,199,172,119,43,122,175,23,181,16,180,4,45, +128,213,132,173,53,125,200,50,194,22,0,136,89,162,22,130,150,160,5,192,95,239,87,215,56,54,218,8,91,0,176,85,107,248,154,161,168,133,160,37,104,1,8,91,102,215,97,235,69,28,253,13,0,159,45,249,6,240,99,231,133,167,209,111,12,4,45,0,132,45,179,135,233, +143,33,63,8,91,0,236,220,51,191,175,71,208,242,194,7,64,216,50,194,22,0,172,197,205,253,251,224,150,174,194,94,245,251,249,191,189,38,1,96,151,154,110,158,222,79,99,29,76,248,48,255,234,254,67,240,33,194,22,0,251,113,187,177,247,189,226,254,61,157,29, +42,227,10,45,0,182,227,201,253,7,53,87,33,25,87,108,1,192,126,126,255,95,120,122,189,160,5,45,0,182,160,16,182,140,176,5,0,95,216,242,109,26,238,60,189,130,150,160,5,128,176,101,204,240,186,41,252,8,1,224,247,254,126,143,127,78,238,161,5,0,124,75,219, +205,243,110,126,238,166,182,14,38,168,50,220,99,75,216,2,96,11,246,112,159,169,255,246,52,239,75,25,87,104,1,176,31,69,92,177,101,92,177,5,192,254,62,255,236,229,253,122,117,183,13,112,133,22,0,48,70,27,87,108,49,79,21,87,108,1,176,78,255,179,179,247, +235,85,17,180,0,128,41,218,12,97,235,167,110,94,119,243,201,74,152,240,65,89,216,2,96,77,158,237,232,177,174,238,107,135,130,22,0,48,71,31,178,14,25,174,216,18,182,152,162,202,49,108,61,177,14,0,22,170,127,143,42,118,246,120,87,245,181,67,65,11,0,120, +12,97,139,185,170,110,222,101,56,46,188,180,14,0,22,166,244,152,151,77,208,2,0,78,65,216,226,49,31,158,239,34,108,1,176,44,255,229,49,47,155,160,5,0,156,146,176,197,92,101,132,45,0,150,163,216,225,99,94,213,173,0,4,45,0,224,28,30,134,173,151,25,110,38, +15,99,148,17,182,0,184,190,39,30,243,178,9,90,0,192,57,245,97,235,183,12,97,171,63,29,177,181,18,70,42,35,108,1,112,29,197,78,31,183,155,194,3,0,124,67,29,97,139,233,202,12,81,171,191,129,124,101,29,0,92,64,177,227,199,190,154,168,37,104,1,0,151,86,71, +216,98,186,254,107,16,183,221,124,136,176,5,0,231,124,191,93,5,65,11,0,184,150,58,194,22,211,21,17,182,0,96,247,4,45,0,224,218,234,8,91,76,87,68,216,2,128,221,18,180,0,128,165,168,51,132,173,95,187,105,172,131,145,138,8,91,0,176,59,130,22,115,124,178, +2,0,206,232,109,55,79,239,167,177,14,70,42,34,108,1,192,110,8,90,243,237,249,3,246,123,79,63,0,23,122,175,21,182,152,170,200,16,182,62,118,115,200,202,142,32,7,0,198,17,180,152,202,213,89,0,92,90,19,97,139,233,250,144,245,42,195,21,91,135,8,91,0,176, +41,130,214,227,63,96,239,141,171,179,0,184,230,251,174,176,197,84,194,22,0,108,144,160,245,56,237,14,31,179,160,5,192,181,53,17,182,152,78,216,2,128,13,17,180,30,231,63,59,124,204,255,235,105,7,96,33,154,12,81,171,63,25,177,182,14,70,18,182,0,96,3,4, +173,199,127,144,222,155,183,158,118,0,22,166,237,230,121,132,45,166,249,58,108,21,86,2,0,235,33,104,61,254,3,244,158,190,130,215,63,86,55,133,7,96,201,239,203,194,22,83,61,12,91,253,233,136,133,149,0,192,242,9,90,143,247,255,60,86,0,88,148,54,194,22, +243,84,17,182,0,96,21,4,173,199,123,235,177,2,192,34,181,17,182,152,167,138,176,5,0,139,38,104,157,230,195,242,30,66,79,157,125,158,234,8,192,54,222,171,63,135,173,223,226,235,243,140,87,69,216,2,128,69,18,180,78,227,255,238,224,49,250,186,33,0,107,215, +118,243,50,67,216,122,29,97,139,241,170,8,91,0,192,70,221,117,243,199,70,231,206,211,11,192,6,245,55,3,63,116,243,113,195,239,225,230,60,243,123,55,165,31,33,128,205,42,119,252,30,231,253,109,135,158,108,248,5,93,120,122,1,16,182,140,249,230,31,250,249, +224,15,32,104,9,90,87,224,43,135,167,243,62,195,125,57,182,166,127,76,173,167,23,128,13,235,191,122,120,136,175,34,50,239,55,60,119,17,182,0,128,149,235,255,132,183,191,191,194,86,202,236,135,251,199,4,0,123,123,63,63,196,21,91,198,21,91,0,123,85,198, +21,90,120,225,175,122,158,120,58,1,216,121,216,170,178,173,63,172,50,194,22,0,130,150,160,197,119,189,216,192,139,248,133,167,17,0,254,34,108,25,97,11,64,208,18,180,216,133,219,21,191,128,111,61,125,0,32,108,153,147,222,198,161,242,227,3,32,104,9,90, +136,90,98,22,0,8,91,70,216,2,64,208,18,180,56,131,155,149,69,45,49,11,0,132,45,35,108,1,8,90,130,22,252,105,13,81,75,204,2,0,97,203,8,91,0,8,90,240,133,37,223,40,222,13,224,1,224,116,31,128,239,132,26,35,108,1,8,90,130,22,91,251,161,88,210,159,222,246, +255,46,79,60,45,0,32,108,153,69,133,173,27,63,66,0,130,150,160,197,210,244,31,80,222,44,224,69,250,198,135,37,0,16,182,204,34,231,99,55,7,159,213,0,4,45,65,139,37,122,114,165,15,184,253,255,103,97,253,0,112,241,15,198,194,150,17,182,0,214,243,190,45, +104,193,136,31,148,75,220,52,254,214,11,19,0,22,241,190,47,108,25,97,11,96,249,239,215,130,22,140,84,100,184,57,251,187,19,190,16,223,221,255,154,62,252,0,192,242,62,40,175,225,20,100,35,108,1,236,245,125,90,208,130,25,250,15,41,207,50,220,231,234,238, +254,195,203,152,15,56,119,247,255,204,51,31,116,0,96,21,138,8,91,70,216,2,88,154,50,130,214,226,253,203,235,116,117,31,122,139,175,254,179,246,126,0,128,117,191,199,191,202,112,194,29,140,245,169,155,183,221,188,246,121,16,224,164,202,12,23,140,236,209, +211,110,26,47,1,0,0,166,40,226,138,45,51,255,126,169,133,31,33,128,147,40,227,10,173,197,251,183,215,41,0,192,98,180,221,60,239,230,231,110,106,235,96,130,170,155,15,17,182,0,216,9,65,11,0,96,121,218,8,91,204,83,69,216,2,96,7,4,45,0,128,229,106,115,12, +91,253,125,146,62,89,9,35,85,17,182,0,216,48,65,11,0,96,249,218,12,167,218,9,91,76,85,69,216,2,96,131,4,45,0,128,245,232,67,214,33,194,22,211,85,25,194,86,127,106,87,105,29,0,172,157,160,5,0,176,62,194,22,115,149,25,162,150,176,5,192,170,9,90,0,0,235, +37,108,49,87,25,97,11,128,21,19,180,0,0,214,239,235,176,213,90,9,35,149,17,182,0,88,33,65,11,0,96,59,30,134,173,254,116,196,214,74,24,169,140,176,5,192,138,8,90,0,0,219,84,71,216,98,186,50,199,176,245,204,58,0,88,42,65,11,0,96,219,234,8,91,76,87,118, +243,123,134,147,17,43,235,0,96,105,4,45,0,128,125,168,35,108,49,93,209,205,109,132,45,0,22,70,208,2,0,216,151,58,194,22,211,21,17,182,0,88,16,65,11,0,96,159,234,28,195,86,99,29,140,84,68,216,2,96,1,4,45,0,128,125,171,187,121,122,63,141,117,48,82,17,97, +11,128,43,18,180,0,0,232,53,17,182,152,174,200,49,108,29,186,185,177,18,0,46,65,208,2,0,224,161,38,194,22,211,21,221,188,138,176,5,192,133,8,90,0,0,124,75,19,97,139,233,250,144,37,108,1,112,118,130,22,0,0,255,164,137,176,197,116,194,22,0,103,37,104,1, +0,48,70,147,33,106,253,146,225,70,242,48,134,176,5,192,89,8,90,0,0,76,241,190,155,231,221,252,28,97,139,241,132,45,0,78,74,208,2,0,96,142,54,194,22,211,125,14,91,31,51,156,142,88,88,9,0,115,8,90,0,0,60,70,27,97,139,121,170,12,87,108,9,91,0,76,38,104, +1,0,112,10,109,132,45,230,169,34,108,1,48,145,160,5,0,192,41,181,249,50,108,125,178,18,70,170,34,108,1,48,146,160,5,0,192,57,180,57,134,173,215,17,182,24,175,138,176,5,192,15,8,90,0,0,156,83,31,178,14,17,182,152,174,202,49,108,149,214,1,192,67,130,22, +0,0,151,32,108,49,87,213,205,221,253,148,214,1,64,79,208,2,0,224,146,132,45,230,42,35,108,1,112,79,208,2,0,224,26,132,45,230,42,35,108,1,236,158,160,5,0,192,53,61,12,91,47,51,220,76,30,198,40,35,108,1,236,150,160,5,0,192,18,244,97,235,183,12,97,171,63, +29,177,181,18,70,42,35,108,1,236,142,160,5,0,192,210,212,17,182,152,174,204,16,181,222,101,184,145,60,0,27,38,104,1,0,176,84,117,132,45,166,123,210,205,109,55,31,34,108,1,108,150,160,5,0,192,210,213,17,182,152,174,136,176,5,176,89,130,22,0,0,107,81,71, +216,98,186,34,194,22,192,230,8,90,0,0,172,77,157,33,108,253,218,77,99,29,140,84,68,216,2,216,12,65,11,0,128,181,122,219,205,211,251,105,172,131,145,138,8,91,0,171,39,104,1,0,176,118,77,132,45,166,43,50,132,173,143,221,28,186,185,177,18,128,245,16,180, +0,0,216,138,38,194,22,211,245,33,235,85,134,43,182,14,17,182,0,86,65,208,2,0,96,107,154,8,91,76,39,108,1,172,136,160,5,0,192,86,53,57,134,173,183,214,193,72,194,22,192,10,8,90,0,0,108,93,147,225,68,196,254,100,196,218,58,24,73,216,2,88,48,65,11,0,128, +189,104,187,121,30,97,139,105,30,134,173,55,25,110,38,15,192,149,9,90,0,0,236,77,27,97,139,233,250,176,245,34,67,216,234,79,71,44,172,4,224,122,4,45,0,0,246,170,141,176,197,60,85,132,45,128,171,18,180,0,0,216,187,54,194,22,243,84,17,182,0,174,66,208, +2,0,128,65,155,99,216,250,173,155,79,86,194,72,85,132,45,128,139,18,180,0,0,224,75,109,55,47,51,132,173,215,17,182,24,175,138,176,5,112,17,130,22,0,0,124,91,31,178,14,17,182,152,174,202,16,182,126,239,166,180,14,128,211,19,180,0,0,224,159,9,91,204,245, +172,155,187,251,41,173,3,224,116,4,45,0,0,24,71,216,98,174,50,194,22,192,73,9,90,0,0,48,141,176,197,92,101,132,45,128,147,16,180,0,0,96,158,207,97,235,167,12,167,35,182,86,194,72,101,132,45,128,71,17,180,0,0,224,241,234,12,87,108,9,91,76,81,230,24,182, +158,89,7,192,120,130,22,0,0,156,78,29,97,139,233,202,12,39,34,246,39,35,86,214,1,240,99,130,22,0,0,156,94,29,97,139,233,138,110,110,35,108,1,252,144,160,5,0,0,231,83,71,216,98,186,34,194,22,192,63,18,180,0,0,224,252,234,28,195,214,123,235,96,164,34,194, +22,192,55,9,90,0,0,112,57,117,55,191,116,243,180,155,198,58,24,169,136,176,5,240,5,65,11,0,0,46,175,201,16,181,132,45,166,40,114,12,91,47,186,185,177,18,96,175,4,45,0,0,184,158,38,194,22,211,21,221,188,201,16,182,14,17,182,128,29,18,180,0,0,224,250,154, +8,91,76,215,135,172,87,17,182,128,29,18,180,0,0,96,57,154,8,91,76,39,108,1,187,35,104,1,0,192,242,52,57,134,173,218,58,24,73,216,2,118,67,208,2,0,128,229,106,186,121,222,205,207,17,182,24,79,216,2,54,79,208,2,0,128,229,107,35,108,49,221,195,176,213,159, +142,88,88,9,176,21,130,22,0,0,172,71,27,97,139,233,250,176,85,69,216,2,54,68,208,2,0,128,245,105,35,108,49,79,21,97,11,216,0,65,11,0,0,214,171,141,176,197,60,85,132,45,96,197,4,45,0,0,88,191,54,67,216,250,169,155,215,221,124,178,18,70,170,34,108,1,43, +36,104,1,0,192,118,244,33,235,144,225,138,45,97,139,41,170,28,195,214,19,235,0,150,78,208,2,0,128,237,17,182,152,171,234,230,93,55,119,221,148,214,1,44,149,160,5,0,0,219,37,108,49,87,153,33,106,9,91,192,34,9,90,0,0,176,125,194,22,115,149,17,182,128,5, +18,180,0,0,96,63,190,14,91,173,149,48,82,25,97,11,88,16,65,11,0,0,246,231,97,216,234,79,71,108,173,132,145,202,8,91,192,2,8,90,0,0,176,111,117,132,45,166,43,115,12,91,149,117,0,151,38,104,1,0,0,189,58,194,22,211,149,221,220,118,243,33,194,22,112,65,130, +22,0,0,240,80,29,97,139,233,138,8,91,192,5,9,90,0,0,192,183,212,17,182,152,174,136,176,5,92,128,160,5,0,0,252,147,58,199,176,213,88,7,35,21,17,182,128,51,18,180,0,0,128,49,234,110,158,222,79,99,29,140,84,68,216,2,206,64,208,2,0,0,166,104,34,108,49,93, +145,99,216,58,116,115,99,37,192,99,8,90,0,0,192,28,77,132,45,166,43,186,121,21,97,11,120,36,65,11,0,0,120,140,38,194,22,211,245,33,75,216,2,102,19,180,0,0,128,83,104,34,108,49,157,176,5,204,34,104,1,0,0,167,212,100,136,90,253,201,136,181,117,48,146,176, +5,76,34,104,1,0,0,231,208,118,243,60,194,22,211,124,29,182,10,43,1,190,69,208,2,0,0,206,169,141,176,197,116,15,195,86,127,58,98,97,37,192,67,130,22,0,0,112,9,109,132,45,230,169,34,108,1,95,17,180,0,0,128,75,106,35,108,49,79,21,97,11,184,39,104,1,0,0, +215,208,230,203,176,245,201,74,24,169,138,176,5,187,39,104,1,0,0,215,212,230,24,182,94,71,216,98,188,42,194,22,236,150,160,5,0,0,44,65,31,178,14,17,182,152,174,202,49,108,149,214,1,251,32,104,1,0,0,75,34,108,49,87,213,205,221,253,148,214,1,219,38,104, +1,0,0,75,36,108,49,87,25,97,11,54,79,208,2,0,0,150,76,216,98,174,50,194,22,108,150,160,5,0,0,172,193,195,176,213,223,68,190,181,18,70,42,35,108,193,230,8,90,0,0,192,154,244,97,171,142,176,197,116,101,132,45,216,12,65,11,0,0,88,171,58,194,22,211,149,25, +162,214,187,12,55,146,7,86,72,208,2,0,0,214,174,142,176,197,116,79,186,185,237,230,67,132,45,88,29,65,11,0,0,216,138,58,194,22,211,21,17,182,96,117,4,45,0,0,96,107,234,8,91,76,87,68,216,130,213,16,180,0,0,128,173,170,51,132,173,167,221,52,214,193,72, +69,132,45,88,60,65,11,0,0,216,186,38,67,212,18,182,152,162,200,151,97,235,198,74,96,57,4,45,0,0,96,47,154,8,91,76,87,228,24,182,14,17,182,96,17,4,45,0,0,96,111,154,8,91,76,215,135,172,87,17,182,96,17,4,45,0,0,96,175,154,8,91,76,39,108,193,2,8,90,0,0, +192,222,53,57,134,173,183,214,193,72,194,22,92,145,160,5,0,0,48,104,186,249,53,195,201,136,181,117,48,146,176,5,87,32,104,1,0,0,124,169,237,230,121,132,45,166,121,24,182,222,100,184,153,60,112,38,130,22,0,0,192,183,181,17,182,152,174,15,91,47,50,132, +173,254,116,196,194,74,224,244,4,45,0,0,128,127,214,70,216,98,158,42,194,22,156,133,160,5,0,0,48,78,27,97,139,121,170,8,91,112,82,130,22,0,0,192,52,109,142,97,235,117,55,159,172,132,145,170,8,91,112,18,130,22,0,0,192,60,109,134,83,237,132,45,166,170, +34,108,193,163,8,90,0,0,0,143,211,135,172,67,132,45,166,171,50,132,173,187,110,74,235,128,241,4,45,0,0,128,211,16,182,152,171,204,16,181,132,45,24,73,208,2,0,0,56,45,97,139,185,202,8,91,48,138,160,5,0,0,112,30,194,22,115,149,17,182,224,31,9,90,0,0,0, +231,245,57,108,253,148,225,116,196,214,74,24,169,140,176,5,223,36,104,1,0,0,92,78,157,225,138,45,97,139,41,202,28,195,214,51,235,0,65,11,0,0,224,26,234,8,91,76,87,118,243,123,134,147,17,43,235,96,207,4,45,0,0,128,235,169,35,108,49,93,209,205,109,132, +45,118,76,208,2,0,0,184,190,58,194,22,211,21,17,182,216,41,65,11,0,0,96,57,234,28,195,214,123,235,96,164,34,194,22,59,35,104,1,0,0,44,79,221,205,47,221,60,237,166,177,14,70,42,34,108,177,19,130,22,0,0,192,114,53,25,162,150,176,197,20,69,142,97,235,69, +55,55,86,194,214,8,90,0,0,0,203,215,68,216,98,186,162,155,55,25,194,214,33,194,22,27,34,104,1,0,0,172,71,19,97,139,233,250,144,245,42,194,22,27,34,104,1,0,0,172,79,19,97,139,233,132,45,54,67,208,2,0,0,88,175,38,67,212,234,111,32,95,91,7,35,9,91,172,158, +160,5,0,0,176,126,239,187,121,222,205,207,17,182,24,79,216,98,181,4,45,0,0,128,237,104,35,108,49,221,231,176,245,49,195,233,136,133,149,176,116,130,22,0,0,192,246,180,17,182,152,167,202,112,197,150,176,197,162,9,90,0,0,0,219,213,70,216,98,158,42,194, +22,11,38,104,1,0,0,108,95,27,97,139,121,170,8,91,44,144,160,5,0,0,176,31,109,134,176,245,83,55,175,187,249,100,37,140,84,69,216,98,65,4,45,0,0,128,253,233,67,214,33,195,21,91,194,22,83,84,57,134,173,39,214,193,181,8,90,0,0,0,251,37,108,49,87,213,205, +187,110,238,186,41,173,131,75,19,180,0,0,0,16,182,152,171,204,16,181,132,45,46,74,208,2,0,0,224,51,97,139,185,202,8,91,92,144,160,5,0,0,192,215,30,134,173,151,25,110,38,15,99,148,17,182,184,0,65,11,0,0,128,239,233,195,214,111,25,194,86,127,58,98,107, +37,140,84,70,216,226,140,4,45,0,0,0,198,168,35,108,49,93,153,99,216,170,172,131,83,17,180,0,0,0,152,162,142,176,197,116,101,55,183,221,124,136,176,197,9,8,90,0,0,0,204,81,71,216,98,186,34,194,22,39,32,104,1,0,0,240,24,117,132,45,166,43,34,108,241,8,130, +22,0,0,0,167,80,103,8,91,191,118,211,88,7,35,21,17,182,152,65,208,2,0,0,224,148,222,118,243,244,126,26,235,96,164,34,194,22,19,8,90,0,0,0,156,67,19,97,139,233,138,12,97,235,99,55,135,110,110,172,132,111,17,180,0,0,0,56,167,38,194,22,211,245,33,235,85, +134,43,182,14,17,182,248,138,160,5,0,0,192,37,52,17,182,152,78,216,226,155,4,45,0,0,0,46,169,137,176,197,116,194,22,95,16,180,0,0,0,184,134,38,67,212,234,79,70,172,173,131,145,132,45,254,36,104,1,0,0,112,77,109,55,207,35,108,49,205,215,97,171,176,146, +125,17,180,0,0,0,88,130,54,194,22,211,61,12,91,253,233,136,133,149,236,131,160,5,0,0,192,146,180,17,182,152,167,138,176,181,27,130,22,0,0,0,75,212,70,216,98,158,42,194,214,230,9,90,0,0,0,44,89,155,99,216,250,173,155,79,86,194,72,85,132,173,205,18,180, +0,0,0,88,131,182,155,151,25,194,214,235,8,91,140,87,69,216,218,28,65,11,0,0,128,53,233,67,214,33,194,22,211,85,25,194,214,239,221,148,214,177,110,130,22,0,0,0,107,36,108,49,215,179,110,238,238,167,180,142,117,18,180,0,0,0,88,51,97,139,185,202,8,91,171, +37,104,1,0,0,176,5,194,22,115,149,17,182,0,0,0,128,5,184,201,241,158,73,127,24,51,97,246,252,154,41,215,242,3,238,10,45,0,0,0,182,168,191,66,171,206,112,197,214,243,12,167,36,194,24,133,21,44,159,160,5,0,0,192,214,213,17,182,96,83,4,45,0,0,0,246,162, +142,176,5,155,32,104,1,0,0,176,55,117,132,45,88,53,65,11,0,0,128,189,170,35,108,193,42,9,90,0,0,0,236,93,157,33,108,61,237,166,177,14,88,62,65,11,0,0,0,6,77,134,168,37,108,193,194,9,90,0,0,0,240,165,38,194,22,44,154,160,5,0,0,0,223,214,68,216,130,69, +18,180,0,0,0,224,159,53,17,182,96,81,4,45,0,0,0,24,167,201,49,108,213,214,1,215,35,104,1,0,0,192,52,77,55,207,51,156,140,88,91,7,92,158,160,5,0,0,0,243,180,17,182,224,42,4,45,0,0,0,120,156,54,194,22,92,148,160,5,0,0,0,167,209,70,216,130,139,16,180,0, +0,0,224,180,218,8,91,112,86,130,22,0,0,0,156,71,155,99,216,122,221,205,39,43,129,211,16,180,0,0,0,224,188,218,110,14,17,182,224,100,4,45,0,0,0,184,140,62,100,29,34,108,193,163,9,90,0,0,0,112,89,194,22,60,146,160,5,0,0,0,215,33,108,193,76,130,22,0,0,0, +92,151,176,5,19,9,90,0,0,0,176,12,159,195,214,79,25,78,71,108,173,4,190,77,208,2,0,0,128,229,169,51,92,177,37,108,193,55,8,90,0,0,0,176,92,117,132,45,248,27,65,11,0,0,0,150,175,142,176,5,127,17,180,0,0,0,96,61,234,8,91,32,104,1,0,0,192,10,213,57,134, +173,198,58,216,27,65,11,0,0,0,214,171,238,230,233,253,52,214,193,94,8,90,0,0,0,176,126,77,132,45,118,68,208,2,0,0,128,237,104,34,108,177,3,130,22,0,0,0,108,79,19,97,139,13,19,180,0,0,0,96,187,154,8,91,108,144,160,5,0,0,0,219,215,100,136,90,191,100,184, +145,60,172,154,160,5,0,0,0,251,241,190,155,231,221,252,28,97,139,21,19,180,0,0,0,96,127,218,8,91,172,152,160,5,0,0,0,251,213,70,216,98,133,4,45,0,0,0,160,141,176,197,138,8,90,0,0,0,192,103,109,190,12,91,159,172,132,37,18,180,0,0,0,128,175,181,57,134, +173,215,17,182,88,24,65,11,0,0,0,248,158,62,100,29,34,108,177,48,130,22,0,0,0,240,35,194,22,139,34,104,1,0,0,0,99,9,91,44,130,160,5,0,0,0,76,37,108,113,85,130,22,0,0,0,48,215,195,176,245,50,195,205,228,225,236,4,45,0,0,0,224,177,250,176,245,91,134,176, +213,159,142,216,90,9,231,36,104,1,0,0,0,167,84,71,216,226,204,4,45,0,0,0,224,28,234,8,91,156,137,160,5,0,0,0,156,83,29,97,139,19,19,180,0,0,0,128,75,168,35,108,113,34,130,22,0,0,0,112,73,117,134,176,245,107,55,141,117,0,0,0,0,176,54,101,55,119,221,252, +97,174,62,79,188,28,1,0,0,0,198,43,35,108,93,123,0,0,0,0,152,161,140,176,37,104,1,0,0,0,172,80,25,97,235,146,115,183,166,23,135,155,194,3,0,0,0,75,212,116,243,244,126,222,90,199,217,181,107,250,151,21,180,0,0,0,128,37,107,50,156,136,216,159,140,88,91, +199,217,252,175,21,0,0,0,0,156,71,209,205,109,124,69,208,9,135,0,0,0,0,43,83,68,216,58,213,124,240,114,2,0,0,0,184,156,34,194,214,99,231,141,151,17,0,0,0,192,229,21,17,182,124,221,16,0,0,0,96,133,138,12,87,28,125,140,80,53,102,222,121,201,0,0,0,0,44, +195,77,55,135,8,91,63,154,202,75,5,0,0,0,96,89,132,45,55,131,7,0,0,0,88,37,97,203,213,89,0,0,0,0,171,36,108,185,119,22,0,0,0,192,42,237,61,108,57,217,16,0,0,0,96,165,250,176,85,101,184,159,212,94,98,214,193,211,14,0,0,0,176,13,85,182,31,182,238,60,205, +0,0,0,0,219,83,101,155,97,171,127,76,55,158,94,0,0,0,128,237,170,178,157,176,213,223,43,204,125,179,0,0,0,0,118,162,202,186,195,150,152,5,0,0,0,176,83,85,55,239,34,102,1,0,0,0,176,50,101,134,155,171,47,61,102,245,241,77,204,2,0,0,0,224,47,101,150,27, +182,126,143,27,192,3,0,0,0,240,29,101,150,19,182,250,175,24,62,243,148,0,0,0,0,48,70,153,235,134,173,219,184,42,11,0,0,0,128,25,202,92,54,108,245,33,171,176,118,0,0,0,0,30,171,232,230,77,134,175,1,158,58,98,125,232,230,16,33,11,0,0,0,128,51,233,239,107, +213,199,173,254,228,193,199,156,90,216,255,26,187,63,185,240,95,94,79,0,0,0,0,23,87,102,184,186,170,159,255,147,191,71,170,255,220,255,181,189,159,198,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,231,254,191,0,3,0,11,98,146,161,132,82,43,233,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::saw_wave_png = (const char*) temp_c4474a8; + +//================== sine_wave.png ================== +static const unsigned char temp_77db788[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,4,180,0,0,2,171,8,6,0,0,0,232,11,212,215,0,0,0,9,112,72,89,115,0,0,23,18,0,0,23,18,1,103,159,210,82,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101, +97,100,121,113,201,101,60,0,0,49,204,73,68,65,84,120,218,236,221,175,151,36,199,149,40,224,24,205,3,122,200,13,197,156,203,196,92,102,102,78,49,9,109,137,237,178,52,123,102,229,191,96,211,232,157,69,101,182,176,198,200,107,84,18,178,141,170,133,158,88, +143,153,30,170,22,211,67,51,98,54,242,203,112,85,107,122,52,61,221,153,89,249,43,50,191,239,156,123,122,108,31,219,163,232,200,31,113,51,238,141,15,2,0,0,0,0,36,228,3,67,0,0,0,0,64,74,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90, +0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0, +64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69, +66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0, +0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,32,61,87, +85,228,134,1,0,0,88,170,255,97,8,0,6,19,19,81,171,123,63,127,114,254,121,255,63,187,212,245,189,63,191,174,226,175,247,254,245,237,57,226,191,255,210,175,3,0,0,72,213,51,67,0,208,169,152,148,202,206,63,127,122,254,243,93,76,205,237,57,190,186,247,231, +107,191,66,0,0,96,234,36,180,0,218,203,194,41,113,245,203,243,207,124,38,255,92,113,247,214,109,56,237,238,122,121,239,95,3,0,0,76,130,132,22,64,61,119,37,129,121,21,63,59,255,188,90,208,63,127,44,83,188,14,167,221,92,241,167,146,69,0,0,96,52,18,90,0, +15,187,107,188,254,203,243,207,149,33,121,203,109,120,59,193,117,107,72,0,0,128,161,72,104,1,188,17,147,88,235,42,254,245,252,147,250,226,142,173,235,112,74,112,125,97,56,0,0,0,0,250,147,85,177,169,226,80,197,63,68,103,177,175,162,8,211,108,134,15,0, +0,0,144,156,44,156,146,88,55,65,226,105,200,228,214,149,169,7,0,0,0,80,95,22,36,177,166,148,220,2,0,0,0,224,61,98,47,44,229,132,211,139,87,85,236,130,94,101,0,0,0,0,255,148,85,81,86,113,12,18,71,41,37,183,156,36,9,0,0,0,44,78,220,237,19,75,218,36,137, +210,141,88,18,90,152,202,0,0,0,192,156,197,70,227,177,55,150,221,88,243,138,248,251,44,130,70,242,0,0,0,192,140,196,242,180,88,166,38,249,51,255,114,196,50,72,108,1,0,0,0,9,203,131,38,239,18,91,0,0,0,0,9,200,131,68,150,56,69,220,153,151,185,36,0,0,0, +128,169,202,131,68,150,144,216,2,0,0,0,18,144,7,137,44,33,177,5,0,0,0,36,32,15,18,89,162,93,148,65,143,45,0,0,0,96,64,121,144,200,18,154,199,3,0,0,0,9,200,170,216,7,137,24,209,109,28,171,40,92,94,0,0,0,64,151,226,14,154,50,156,118,212,72,192,136,62,19, +91,185,203,13,0,0,0,184,212,58,156,18,13,18,46,98,168,136,229,172,185,75,15,0,0,0,104,42,11,250,100,137,241,79,68,212,95,11,0,0,0,120,210,93,121,161,132,138,152,74,227,248,141,203,18,0,0,0,120,159,34,40,47,20,211,45,67,92,185,68,1,0,0,128,59,49,81,160, +188,80,164,16,165,203,21,0,0,0,40,131,36,137,112,26,34,0,0,0,144,128,184,43,235,38,72,142,8,77,227,1,0,0,128,4,196,38,219,18,34,98,46,77,227,215,46,105,0,0,0,152,175,44,232,149,37,230,219,52,62,115,137,3,0,192,244,60,55,4,192,5,226,46,150,63,85,241,177, +161,96,134,178,112,58,165,243,255,85,241,210,112,0,0,0,64,218,98,143,161,125,176,131,71,44,39,246,65,111,45,0,0,152,140,103,134,0,104,40,183,184,103,161,110,171,248,60,216,173,5,0,0,163,251,192,16,0,53,197,4,214,54,156,250,10,73,102,177,68,89,56,157, +226,185,49,20,0,0,48,46,59,180,128,58,86,85,236,206,63,129,16,174,195,105,183,214,107,67,1,0,0,195,179,67,11,120,74,17,78,187,178,36,179,224,141,188,138,227,249,39,0,0,48,48,9,45,224,125,98,89,225,238,28,74,12,225,225,107,36,38,123,183,134,2,0,0,134, +165,228,16,120,72,22,78,141,223,237,202,130,122,98,163,248,88,130,120,107,40,0,0,160,127,118,104,1,63,182,14,167,198,215,146,89,80,223,234,124,221,172,13,5,0,0,244,239,185,33,0,238,137,165,83,191,171,226,67,67,1,141,197,235,230,223,194,169,20,241,47, +134,3,0,0,250,163,228,16,8,231,5,120,44,49,204,13,5,116,226,58,56,5,17,0,0,122,163,228,16,200,131,211,218,160,143,235,202,233,160,0,0,208,19,9,45,88,182,242,188,232,118,138,33,116,111,117,190,190,244,213,2,0,128,142,233,161,5,203,20,19,88,127,168,226, +127,25,10,232,213,93,95,173,88,226,127,109,56,0,0,160,27,18,90,176,60,49,153,21,119,141,228,134,2,6,19,175,183,172,138,175,170,248,155,225,0,0,128,203,104,10,15,203,114,87,2,165,196,16,198,241,50,156,154,197,223,26,10,0,0,104,79,15,45,88,142,34,72,102, +193,216,98,82,249,38,216,33,9,0,0,23,145,208,130,101,216,84,177,11,146,89,48,5,119,101,191,133,161,0,0,128,118,148,28,194,252,237,44,156,97,178,94,84,241,43,195,0,0,0,205,104,10,15,243,21,119,129,252,159,42,62,53,20,48,89,177,4,49,171,226,75,67,1,0,0, +245,41,57,132,249,46,146,15,231,159,192,180,21,225,212,87,75,73,48,0,0,212,36,161,5,243,147,7,201,44,72,205,93,18,58,51,20,0,0,240,52,9,45,152,151,34,56,201,16,82,117,119,2,162,100,52,0,0,60,65,66,11,230,227,238,36,67,32,93,119,39,32,230,134,2,0,0,222, +207,41,135,48,15,78,50,132,249,137,167,31,190,48,12,0,0,240,46,167,28,66,250,36,179,96,158,214,225,244,225,233,218,80,0,0,192,219,36,180,32,109,146,89,48,111,121,56,53,138,255,210,80,0,0,192,27,18,90,144,166,216,103,231,79,225,180,131,3,152,183,213,57, +254,82,197,223,12,7,0,0,232,161,5,41,186,107,26,237,36,52,88,150,151,85,124,82,197,107,67,1,0,192,210,57,229,16,210,34,153,5,203,181,58,95,255,87,134,2,0,128,165,147,208,130,116,100,65,50,11,150,78,82,11,0,0,130,146,67,176,136,101,74,98,41,217,203,243, +159,191,106,240,223,251,73,120,59,209,153,157,131,249,82,126,8,0,192,162,73,104,193,244,73,102,205,207,203,115,252,245,252,243,126,34,171,75,121,120,147,220,250,101,144,232,154,227,60,146,212,2,0,96,145,36,180,96,218,36,179,210,23,147,13,215,225,148, +188,138,63,239,18,88,99,137,115,41,15,167,4,87,30,148,176,166,78,82,11,0,128,69,146,208,130,233,146,204,74,215,109,21,95,84,241,251,208,207,206,171,46,101,225,77,130,107,109,190,37,73,82,11,0,0,128,73,136,201,172,87,85,252,67,36,19,55,85,148,33,253,29, +79,241,239,191,173,226,232,119,154,220,252,147,140,4,0,0,96,212,132,130,100,86,26,17,147,62,101,152,111,95,170,188,138,157,249,40,169,5,0,0,0,143,145,204,74,35,246,225,84,158,183,36,241,159,87,114,75,82,11,0,0,0,222,34,153,101,55,86,10,174,206,227,96, +174,78,55,94,5,205,254,1,0,0,24,128,100,214,116,35,54,230,95,155,162,239,184,75,108,233,181,53,221,164,150,157,90,0,0,0,244,70,50,107,186,137,172,220,244,172,165,8,18,91,202,15,1,0,0,88,12,201,44,137,172,57,41,130,196,150,164,22,0,0,0,179,38,153,37,145, +53,87,69,144,216,146,212,2,0,0,96,118,36,179,36,178,230,78,243,120,73,45,0,0,0,102,68,50,107,58,167,22,230,166,99,239,238,18,91,230,220,52,146,90,0,0,0,208,152,100,214,52,78,127,43,77,197,193,101,85,236,204,191,209,99,103,42,2,0,0,208,132,100,214,248, +177,63,39,86,24,247,58,56,152,139,146,90,0,0,0,76,95,44,187,186,177,144,86,94,200,15,54,65,130,87,82,11,0,0,128,201,146,204,26,183,188,112,99,10,78,86,22,78,187,230,204,85,73,45,0,0,0,38,68,50,107,220,211,11,51,83,48,9,235,112,218,69,103,222,14,31,91, +211,15,0,0,128,31,179,251,100,156,176,43,43,61,49,249,187,53,119,71,137,194,244,3,0,0,224,142,19,221,134,143,184,27,110,101,234,37,45,15,118,53,74,106,1,0,0,48,10,201,44,165,83,92,198,110,45,73,45,0,0,0,6,84,90,24,59,193,144,78,196,222,90,78,66,28,246, +16,5,59,28,1,0,0,22,168,176,40,30,252,148,182,43,211,110,214,226,239,247,96,174,75,106,1,0,0,208,143,194,98,120,208,69,119,97,202,45,74,105,222,15,122,125,101,166,28,0,0,192,252,229,22,193,26,191,51,200,117,118,116,13,12,118,157,217,253,8,0,0,48,99,49, +185,162,207,207,48,177,183,200,94,188,171,243,60,112,61,72,106,1,0,0,112,193,226,90,50,107,152,216,152,110,220,179,113,77,12,18,7,83,13,0,0,96,94,98,50,235,198,130,87,147,106,70,147,7,9,229,161,14,95,0,0,0,96,38,148,61,13,179,59,68,201,19,143,201,130, +196,178,164,22,0,0,0,181,236,44,112,123,143,210,52,163,166,43,215,164,178,95,0,0,0,30,167,119,79,255,37,134,107,211,140,22,74,215,79,239,81,152,102,0,0,0,233,41,44,104,245,203,98,210,214,65,95,173,190,35,55,205,0,0,0,210,177,178,144,237,53,98,31,36,253, +178,232,234,90,61,186,166,36,158,1,0,0,44,144,237,250,232,187,225,180,100,22,93,138,243,233,224,218,234,45,142,174,89,0,0,128,233,47,140,157,162,214,95,108,77,49,122,164,89,124,191,187,42,1,0,0,152,32,201,44,13,166,73,223,214,181,214,235,238,74,0,0,0, +38,198,238,142,254,122,240,228,166,23,3,42,92,119,189,69,105,122,1,0,0,76,71,105,161,218,91,153,146,134,210,140,193,9,136,118,91,2,0,0,204,90,97,129,234,36,67,102,201,1,15,253,133,68,53,0,0,128,5,175,100,22,244,120,141,235,141,215,79,41,177,164,22,0, +0,192,8,174,130,100,86,31,113,8,146,89,76,239,90,151,212,146,184,6,0,0,176,192,21,78,65,35,185,107,222,193,15,253,36,181,0,0,0,24,136,133,173,100,22,174,125,225,218,7,0,0,72,70,105,1,106,65,203,162,73,106,117,31,165,105,5,0,0,208,159,194,194,179,243, +216,152,86,36,72,82,171,251,88,155,86,0,0,0,221,115,162,97,247,81,152,86,36,76,82,203,201,135,0,0,0,147,230,68,67,201,44,120,136,164,150,147,15,1,0,0,38,201,137,134,146,89,240,24,73,173,110,99,111,74,1,0,0,88,172,74,102,129,251,132,222,122,0,0,0,11,82, +90,88,74,102,65,77,146,90,221,70,110,74,1,0,0,52,183,182,160,148,204,130,134,36,181,186,109,18,159,153,82,0,0,0,245,57,209,80,50,11,218,146,212,210,36,30,0,0,96,112,154,192,75,102,193,165,36,181,186,139,157,233,4,0,0,240,180,189,5,164,100,22,116,64,82, +75,147,120,0,0,128,65,108,44,28,37,179,160,67,146,90,154,196,3,0,0,244,42,183,96,148,204,130,30,216,245,169,73,60,0,0,64,47,178,160,9,188,100,22,244,67,95,62,77,226,1,0,0,44,54,131,100,22,184,207,104,18,15,0,0,176,104,122,220,88,100,194,16,36,181,36, +207,1,0,0,58,81,88,24,74,102,193,128,36,181,186,139,149,233,4,0,0,44,209,202,130,80,50,11,70,16,147,90,71,247,142,139,227,24,244,211,2,0,0,22,184,160,212,4,190,155,6,205,64,115,43,247,160,78,226,96,42,1,0,0,75,114,176,16,116,218,24,140,76,82,171,155, +216,154,74,0,0,192,18,108,45,0,37,179,96,34,148,62,119,19,107,83,9,0,0,152,179,181,133,223,197,17,119,148,100,166,18,116,166,112,95,233,228,190,164,73,60,0,0,48,75,89,80,222,99,209,8,211,84,184,191,216,57,10,0,64,63,158,27,2,18,23,251,102,101,134,161, +181,215,85,124,82,197,75,67,1,157,139,215,213,179,42,114,67,209,218,71,231,248,210,80,0,0,0,115,161,111,214,229,81,152,70,208,187,157,123,205,197,177,49,141,0,0,128,57,208,55,75,50,11,82,34,169,117,121,40,141,6,0,0,146,22,23,53,250,102,93,22,59,211,8, +6,119,227,222,115,113,191,63,253,180,0,0,128,36,93,89,20,94,28,123,211,8,220,191,18,141,131,105,4,0,0,164,72,217,142,19,195,32,101,146,90,151,71,105,26,1,0,0,41,41,44,228,46,138,99,144,204,130,41,80,54,125,121,228,166,17,0,0,96,1,184,140,222,51,26,42, +195,180,238,105,238,77,250,105,1,0,0,51,166,68,199,110,6,152,163,194,189,73,63,45,0,0,218,121,110,8,72,192,127,85,241,169,97,104,237,87,85,124,97,24,96,114,94,86,241,44,72,56,183,149,157,199,239,218,80,0,0,0,83,83,4,187,16,52,79,134,121,115,216,133,29, +168,0,0,192,140,232,155,117,89,236,76,33,72,134,178,106,253,180,0,0,128,25,208,55,235,178,184,49,133,192,61,47,232,167,5,0,0,48,40,37,56,237,227,24,236,86,128,20,217,149,170,196,26,0,0,72,88,97,97,118,81,233,205,202,20,130,100,229,238,99,250,105,1,0, +0,233,177,67,225,178,88,155,66,144,188,194,189,76,63,45,0,0,32,29,122,200,92,22,27,83,8,102,99,235,158,166,159,22,0,0,96,1,231,68,67,32,53,123,247,54,253,180,0,0,128,105,91,91,128,57,209,16,120,139,93,171,151,133,126,130,0,0,64,175,178,160,111,150,19, +13,129,135,232,43,232,254,8,0,0,76,148,29,8,78,52,4,222,207,14,214,246,177,55,125,0,0,128,62,232,155,229,68,67,224,105,165,123,158,123,37,0,0,48,13,118,29,56,209,16,168,79,147,248,246,187,89,51,211,7,0,0,232,66,22,244,133,113,162,33,208,132,38,241,237, +227,96,250,0,0,0,93,56,88,96,181,62,209,80,147,99,88,46,77,226,219,71,105,250,0,0,0,151,40,45,172,148,205,0,173,41,215,110,31,14,210,0,0,0,90,201,45,168,52,54,6,46,86,186,39,182,138,99,176,203,21,0,0,104,232,234,188,152,176,168,82,42,3,92,78,147,120, +125,8,1,0,0,139,175,201,198,222,212,1,30,160,73,188,29,175,0,0,64,207,244,124,81,30,3,116,79,147,120,61,9,1,0,128,158,100,22,92,173,23,92,26,24,3,79,41,220,47,91,197,193,212,1,0,72,215,115,67,192,0,98,201,220,199,134,161,177,95,87,241,103,195,0,60,225, +101,56,237,228,252,133,161,104,36,171,226,89,21,215,134,2,0,0,248,177,77,176,11,160,77,108,77,29,160,33,253,180,218,133,157,176,0,0,192,91,86,22,74,173,226,198,212,1,90,136,187,180,148,119,183,187,231,234,85,8,0,0,252,192,110,129,118,125,179,44,172,128, +182,114,247,81,187,98,1,0,128,246,182,22,72,74,95,128,81,40,245,110,23,107,83,7,0,0,150,45,183,48,106,21,27,83,7,232,200,206,61,213,14,89,0,0,160,190,184,24,56,90,24,53,142,189,169,3,116,124,47,86,246,221,60,14,166,14,0,0,44,211,222,130,168,113,28,131, +93,1,64,247,98,9,179,38,241,118,203,2,0,0,79,40,44,132,244,205,2,38,101,237,30,235,190,12,0,0,188,95,22,236,4,176,19,0,152,34,135,116,52,143,88,174,105,231,44,0,0,44,192,193,2,168,113,236,76,27,192,61,122,178,177,53,109,0,0,96,222,28,17,239,235,63,48, +109,241,126,99,23,109,243,88,155,58,0,0,48,79,43,11,158,86,71,195,235,207,2,12,45,119,255,109,117,191,246,241,1,0,0,102,200,177,240,205,163,48,109,128,145,148,238,193,141,227,96,218,0,0,192,188,104,52,172,111,22,144,30,253,180,28,224,1,0,0,139,149,91, +224,232,155,5,36,73,63,173,118,161,84,28,0,0,102,176,24,58,90,220,232,155,5,36,43,119,95,246,81,2,0,32,101,207,13,1,45,252,215,121,49,68,125,191,174,226,207,134,1,152,136,219,42,158,185,151,55,242,81,21,31,86,241,23,67,1,0,0,233,137,71,152,251,82,175, +111,22,48,15,250,105,53,143,220,180,1,0,128,180,232,187,162,68,5,112,95,95,122,28,221,215,1,0,32,45,123,11,25,125,179,128,217,201,221,175,237,188,5,0,128,185,218,88,192,52,142,194,180,1,18,81,186,103,55,142,181,105,3,0,0,211,150,5,37,41,190,222,3,115, +167,159,86,243,93,184,74,15,1,0,96,194,110,44,92,244,87,1,102,79,63,173,230,177,55,109,0,0,96,154,74,11,150,198,161,111,22,144,170,220,61,92,233,33,0,0,164,110,101,161,210,56,54,166,13,144,184,173,123,185,210,67,0,0,72,153,82,67,165,39,128,251,191,112, +255,7,0,128,100,148,22,40,250,102,1,139,101,135,174,147,109,1,0,32,57,185,133,137,190,89,192,226,109,220,219,27,151,30,102,166,13,0,0,140,35,238,50,58,90,152,232,155,5,80,57,184,199,55,138,131,41,3,0,0,227,208,12,216,226,5,224,78,252,200,241,202,189, +222,71,14,0,0,152,178,220,66,196,201,86,0,63,178,118,191,87,122,8,0,0,83,165,212,176,121,228,166,13,176,16,118,239,218,189,11,0,0,147,180,179,0,105,20,91,83,6,88,144,248,209,227,198,189,95,233,33,0,0,76,137,114,146,102,113,19,148,26,2,203,179,114,255, +87,122,8,0,0,83,161,225,111,243,88,153,54,192,66,109,60,3,148,30,2,0,192,20,236,45,56,26,69,105,202,0,11,119,240,44,80,122,8,0,0,99,82,106,232,75,59,64,83,118,246,42,61,4,0,0,11,18,11,18,128,228,248,32,226,131,8,0,192,168,158,27,130,197,250,83,21,31, +27,134,218,254,189,138,175,13,3,192,63,125,19,78,73,126,61,5,235,137,99,245,172,138,107,67,1,0,0,237,105,234,219,44,246,166,12,192,59,226,78,223,163,103,132,67,69,0,0,96,8,89,80,106,216,36,142,231,69,27,0,239,90,121,78,52,138,27,83,6,0,160,27,74,14,151, +39,238,54,82,106,88,223,231,225,84,90,3,192,187,190,11,167,82,186,220,80,212,242,81,80,122,8,0,0,141,41,53,108,22,91,83,6,160,150,131,103,134,210,67,0,0,232,67,22,148,26,42,11,1,240,140,241,140,1,0,152,1,37,135,203,161,212,176,153,207,194,169,148,6,128, +167,189,174,226,255,86,241,111,134,162,22,165,135,0,0,80,195,58,248,26,222,36,54,166,12,64,43,59,207,16,165,135,0,0,208,133,120,66,159,50,144,250,113,48,101,0,46,122,230,28,61,75,148,30,2,0,192,165,246,22,12,181,35,38,254,50,83,6,224,34,43,207,147,70, +81,154,50,0,0,240,54,165,134,205,98,109,202,0,116,162,244,76,81,122,8,0,0,109,40,53,108,22,123,83,6,160,83,7,207,22,165,135,0,0,208,148,82,195,102,165,134,87,166,12,64,167,178,224,195,138,210,67,0,0,104,64,169,97,179,200,77,25,0,207,163,160,244,16,0, +0,70,163,212,176,89,108,77,25,128,94,237,60,107,148,30,2,0,192,83,148,26,214,143,120,180,188,82,67,128,126,93,157,239,183,158,59,74,15,1,0,224,65,74,59,148,118,0,76,81,238,153,227,249,4,0,0,15,81,106,232,11,56,192,148,109,61,123,148,30,2,0,192,143,41, +53,180,80,0,152,50,165,135,62,188,0,0,192,91,148,26,214,143,184,139,77,41,7,192,56,114,207,33,165,135,0,0,16,41,53,108,22,27,83,6,96,84,74,15,237,40,6,0,0,199,161,55,136,131,233,2,48,58,165,135,74,15,1,0,88,184,220,139,126,163,82,195,204,148,1,152,132, +149,231,146,210,67,0,0,150,201,23,238,102,177,54,101,0,38,165,244,108,82,122,8,0,192,242,232,65,82,63,246,166,11,192,36,221,120,70,41,61,4,0,96,57,114,47,246,141,74,13,175,76,25,128,73,82,122,168,244,16,0,128,133,80,106,168,212,16,96,78,74,207,42,165, +135,0,0,204,159,82,67,165,134,0,115,163,244,80,233,33,0,0,51,150,123,145,175,29,113,23,155,82,67,128,52,40,61,108,22,153,41,3,0,64,74,124,193,174,31,185,233,2,144,148,210,179,171,118,28,76,23,0,0,188,232,207,47,182,166,11,64,146,14,158,97,181,99,99,186, +0,0,48,117,74,49,148,26,2,44,65,22,78,167,211,122,158,213,59,197,55,51,101,0,0,152,50,165,134,74,13,1,150,98,227,89,166,244,16,0,128,244,149,94,216,149,26,2,44,140,210,67,165,135,0,0,36,76,169,97,253,184,49,93,0,102,35,11,74,15,149,30,2,0,144,44,165, +134,245,99,101,186,0,204,138,210,67,165,135,0,0,36,168,244,130,94,59,74,211,5,96,150,148,30,214,143,181,233,2,0,192,216,148,26,42,53,4,64,233,97,211,210,67,167,252,2,0,139,241,220,16,76,210,31,130,126,24,117,125,86,197,119,134,1,96,150,94,87,241,247, +42,62,53,20,79,250,176,138,143,171,248,163,161,0,0,96,12,122,134,40,53,4,224,109,74,15,149,30,2,0,48,97,89,80,90,161,212,16,0,207,71,165,135,0,0,143,82,114,56,45,251,112,42,23,224,105,74,13,1,150,67,233,97,125,74,15,1,0,24,148,82,67,165,134,0,60,78,233, +161,210,67,0,0,38,36,11,74,41,148,26,2,224,121,169,244,16,0,160,22,37,135,211,160,212,176,62,165,134,0,203,165,244,176,190,88,122,248,81,21,95,26,10,0,0,250,160,212,80,169,33,0,205,40,61,172,31,185,233,2,0,64,215,178,160,116,162,110,28,77,23,0,60,63, +91,61,63,149,30,2,0,179,163,228,112,92,74,13,235,251,188,138,91,195,0,64,80,122,216,68,76,102,197,242,195,191,24,10,0,0,186,160,212,176,126,108,77,23,0,30,160,244,80,233,33,0,0,3,138,95,75,149,74,40,149,0,224,50,153,231,169,231,41,0,176,76,207,12,193, +40,98,169,225,218,48,212,242,73,21,215,134,1,128,247,136,59,158,237,228,173,231,119,85,252,198,48,0,192,100,100,231,200,207,255,250,39,85,172,238,253,231,95,157,127,198,118,11,47,207,241,218,176,49,150,152,200,242,165,88,169,33,0,221,81,122,168,244,16, +0,82,16,119,75,23,225,180,201,165,237,46,243,184,235,122,119,254,223,177,251,154,65,39,175,210,8,165,17,0,116,43,243,124,245,124,5,128,9,43,194,41,137,213,199,179,61,254,239,230,134,152,190,237,188,72,251,130,12,64,47,28,182,98,7,52,0,76,241,253,228, +24,134,251,104,85,24,114,250,144,123,129,246,162,13,64,175,148,30,250,112,4,0,83,80,132,225,18,89,15,37,182,60,231,233,204,213,136,147,89,41,4,0,75,145,5,165,135,158,183,0,48,238,187,200,84,62,176,237,61,235,233,194,214,139,179,47,198,0,12,66,233,97, +253,40,77,23,0,232,76,17,166,247,97,237,149,53,54,151,200,189,48,215,142,157,233,2,64,7,148,30,214,143,149,233,2,0,23,155,250,38,150,194,175,136,54,110,188,44,215,206,28,219,14,9,64,23,178,160,244,176,110,220,152,46,0,112,145,84,14,127,179,129,132,70, +74,47,202,181,99,109,186,0,208,33,165,135,74,15,1,160,111,169,109,96,145,212,162,150,149,23,228,70,205,234,0,160,107,74,15,235,239,146,206,76,23,0,104,36,149,157,89,146,90,52,166,212,80,169,33,0,227,202,130,210,195,186,113,48,93,0,160,182,84,147,89,122, +106,241,164,210,139,177,82,67,0,38,65,233,97,253,216,152,46,0,240,164,98,38,207,253,220,175,146,31,203,130,175,193,74,13,1,152,18,165,135,118,77,3,64,23,86,51,90,239,123,238,227,165,217,197,3,192,196,101,158,187,62,54,1,64,7,230,214,90,200,115,159,31, +20,94,132,149,53,0,48,73,165,103,175,118,0,0,112,129,185,182,49,200,253,106,137,187,141,148,26,106,60,11,192,116,57,176,165,94,28,131,93,212,0,112,95,54,227,245,254,209,175,151,210,11,176,163,193,1,152,180,149,231,112,237,216,154,46,0,240,131,185,183, +22,42,252,138,151,203,238,44,165,134,0,164,161,244,44,86,130,0,0,13,44,225,196,100,187,180,22,172,240,210,171,212,16,128,100,40,61,244,114,11,0,117,100,97,57,155,87,244,208,244,98,44,130,82,67,0,166,77,233,97,253,40,77,23,0,22,108,238,165,134,78,60,92, +184,204,203,174,82,67,0,146,83,122,54,215,142,149,233,2,192,2,45,161,212,240,199,225,80,24,147,92,4,165,134,0,76,91,124,97,59,122,70,215,138,27,211,5,128,133,201,194,50,251,100,23,41,253,146,62,48,79,47,246,175,134,224,81,175,171,248,149,97,0,192,243, +41,89,113,135,150,157,214,0,44,201,46,44,115,183,210,47,253,234,151,197,151,91,165,134,0,164,107,235,89,173,23,38,0,220,179,228,42,44,7,194,44,72,238,5,87,137,2,0,73,83,122,168,133,0,0,220,201,194,50,75,13,239,71,150,202,47,75,201,225,229,147,157,247, +83,202,1,192,212,41,61,172,47,15,118,94,3,48,111,113,231,246,210,27,163,103,169,252,69,37,180,22,242,139,30,193,111,171,120,105,24,0,72,192,117,21,191,51,12,181,252,135,23,125,0,102,106,125,142,165,203,83,249,139,74,104,93,230,103,134,224,65,49,145,85, +26,6,0,18,18,63,196,220,26,134,39,197,100,214,206,48,0,224,249,198,216,36,180,46,159,244,188,75,233,6,0,169,81,122,88,159,47,216,0,204,205,82,79,53,124,200,79,83,249,139,74,104,209,53,165,134,0,164,234,58,40,61,244,226,15,192,210,248,80,243,182,204,16, +44,67,60,237,199,169,71,78,53,4,96,62,156,122,88,63,246,166,11,0,51,120,238,47,253,84,195,100,79,53,182,67,139,46,41,213,0,32,117,177,244,240,55,134,161,150,248,53,59,55,12,0,36,204,142,227,132,73,104,209,21,165,134,0,204,197,23,231,192,66,0,128,249, +202,131,82,195,135,220,166,242,23,149,208,162,171,9,95,26,6,0,102,36,238,58,126,109,24,158,148,85,241,31,134,1,128,196,56,213,240,253,190,77,229,47,42,161,117,153,175,12,193,15,47,253,0,48,39,78,61,172,111,19,148,30,2,144,150,248,49,38,51,12,44,253,5, +110,233,13,227,182,166,1,0,51,182,247,172,175,21,71,83,5,128,68,228,158,219,143,70,110,138,184,16,150,242,242,170,111,6,0,115,230,244,163,250,81,154,46,0,36,192,105,198,143,71,102,138,44,135,204,45,0,204,219,218,203,109,237,88,153,46,0,76,88,233,89,253, +104,188,50,69,150,229,102,161,19,125,239,87,15,192,130,40,61,172,23,55,166,10,0,19,181,242,156,158,215,58,95,83,248,203,93,47,240,159,89,163,92,0,150,198,169,135,245,23,11,165,97,0,96,130,156,106,248,52,7,223,45,240,197,109,105,89,219,181,95,59,0,11, +84,4,95,110,149,30,2,144,162,210,179,89,255,44,30,182,164,166,114,74,13,1,88,178,131,151,93,165,135,0,36,37,243,92,174,21,135,212,126,177,74,14,187,241,251,133,252,115,42,53,4,96,233,148,30,214,163,244,16,128,169,80,106,88,207,239,13,193,50,45,229,72, +239,141,95,53,0,252,243,121,232,75,174,210,67,0,60,179,157,110,200,44,236,130,237,135,0,176,20,75,61,229,88,233,33,0,169,200,194,50,54,158,116,17,165,233,178,108,115,222,165,245,42,104,14,7,0,247,57,250,219,75,50,0,211,166,239,101,253,245,254,149,233, +66,25,148,26,2,128,231,190,80,122,8,192,152,148,26,214,143,194,116,225,206,220,78,60,84,42,0,0,15,187,10,203,58,233,216,251,4,0,41,200,130,82,67,173,133,104,37,15,243,218,122,232,139,42,0,44,227,185,175,244,16,128,57,80,106,168,181,16,23,40,131,173,135, +0,176,20,91,47,197,74,15,1,152,4,165,134,90,11,209,129,125,226,147,123,231,87,8,0,181,204,249,96,24,165,135,0,164,34,243,60,86,106,72,119,47,183,55,38,55,0,44,194,218,203,177,210,67,0,70,165,212,208,142,105,58,148,98,82,235,38,56,178,19,0,218,72,125, +119,182,23,105,0,82,165,212,208,135,37,122,144,82,82,75,50,11,0,46,123,230,43,117,80,122,8,192,176,50,207,95,207,95,250,125,193,157,250,87,91,61,179,0,224,114,190,16,251,66,12,192,176,148,26,218,33,205,0,202,224,116,3,0,240,98,45,188,88,3,208,5,31,146, +124,72,98,64,121,21,199,48,157,237,134,94,36,1,160,91,89,80,250,160,244,1,0,207,91,207,219,94,61,119,13,12,238,182,138,223,87,241,247,112,74,38,125,56,194,223,225,117,21,255,89,197,191,87,241,157,95,9,0,116,254,156,253,159,225,244,17,139,199,125,84,197, +179,42,174,13,5,0,13,197,182,62,31,27,134,90,62,179,246,167,107,89,56,245,174,26,42,43,27,179,215,219,160,241,59,0,12,33,181,147,142,199,138,87,231,119,34,0,168,75,169,161,82,67,38,34,59,79,178,190,74,17,143,231,255,125,137,44,0,24,206,202,75,116,237, +56,152,46,0,52,88,63,43,53,84,218,207,68,95,126,227,46,170,99,7,19,119,27,244,200,2,128,49,149,94,166,29,82,3,64,167,28,190,226,240,149,127,122,230,90,152,180,171,243,4,204,171,248,201,19,147,241,101,21,223,135,83,15,138,248,231,215,134,15,0,38,33,126, +164,202,12,195,147,226,187,203,207,195,169,223,40,0,60,36,126,252,216,26,134,90,126,27,148,27,2,0,112,129,60,248,66,172,244,16,128,75,101,65,169,97,147,182,67,179,231,148,67,0,128,126,221,134,211,174,235,95,24,138,90,139,149,184,227,252,107,67,1,192, +143,56,213,176,190,207,131,29,207,0,0,116,32,38,180,250,58,252,197,169,135,0,204,221,218,243,177,118,40,201,4,0,160,83,185,151,236,218,177,55,93,0,56,139,31,133,148,26,214,47,53,188,50,101,0,0,232,218,206,203,118,237,88,155,46,0,132,211,71,14,207,197, +122,145,155,46,0,0,244,193,87,230,102,165,135,190,50,3,44,155,82,195,250,177,51,93,0,0,240,114,174,244,16,128,113,249,8,228,35,16,0,0,19,163,124,66,233,33,0,158,149,158,149,0,0,36,197,87,103,95,157,1,120,63,187,153,237,102,126,210,115,215,9,0,192,224, +254,86,197,223,171,248,212,80,60,233,195,42,62,174,226,143,134,2,96,17,226,71,140,195,249,254,207,227,94,87,241,201,249,189,2,0,0,6,19,95,216,125,93,86,78,1,192,27,74,13,235,199,198,116,1,0,96,12,89,80,122,168,244,16,128,59,74,13,235,199,193,116,1,0, +96,76,27,47,229,250,132,0,160,191,100,104,246,145,39,51,101,0,0,24,155,210,67,165,135,0,75,167,212,80,169,33,0,0,137,201,130,175,210,74,15,1,150,75,169,161,82,67,0,0,18,165,244,80,233,33,192,18,41,53,108,22,43,83,6,0,128,169,81,122,88,63,10,211,5,96, +22,148,26,214,143,210,116,1,0,96,138,178,224,43,181,134,184,0,203,161,212,176,126,220,152,46,0,0,76,153,210,67,125,68,0,150,64,169,161,82,67,0,0,102,70,233,161,147,158,0,230,78,169,161,82,67,0,0,102,38,11,190,90,43,61,4,152,47,165,134,74,13,1,0,152,41, +165,135,74,15,1,230,72,169,161,82,67,0,0,102,78,233,161,210,67,128,185,81,106,168,212,16,0,128,153,203,130,175,216,74,15,1,230,67,169,161,82,67,0,0,22,66,233,161,151,127,128,57,80,106,168,212,16,0,128,133,81,122,168,60,3,32,117,74,13,61,203,0,0,88,152, +44,248,170,237,171,54,64,186,236,54,182,219,24,0,0,139,1,81,99,49,112,101,202,0,76,66,22,124,148,241,81,6,0,128,69,83,122,88,63,182,166,11,128,103,87,80,106,8,0,0,163,203,130,175,220,77,34,55,101,0,70,101,119,177,82,67,0,0,176,56,104,24,199,160,244,16, +96,44,177,116,206,71,24,165,134,0,0,240,3,229,27,245,99,103,186,0,140,226,198,51,72,169,33,0,0,220,183,242,242,223,40,214,166,12,192,160,74,207,30,165,134,0,0,96,177,112,89,196,146,23,165,135,0,195,200,61,119,148,26,2,0,192,99,148,115,212,143,189,233, +2,208,187,248,241,224,232,153,163,212,16,0,0,30,163,244,176,89,108,76,25,128,94,237,61,107,148,26,2,0,64,29,165,69,65,163,210,195,204,148,1,232,197,218,115,70,169,33,0,0,52,161,244,176,126,28,76,23,128,206,101,225,244,209,192,115,70,169,33,0,0,212,166, +244,208,66,2,96,76,7,207,22,165,134,0,0,208,198,214,34,65,169,7,192,8,74,207,20,207,31,0,0,104,203,201,82,205,226,120,30,51,0,218,179,67,216,14,97,0,0,184,88,110,177,208,40,182,166,12,64,107,241,163,128,30,142,205,62,164,0,0,0,239,161,244,176,89,172, +77,25,0,207,155,1,34,55,101,0,0,224,253,148,30,54,139,87,65,233,33,64,83,107,207,15,59,130,1,0,160,107,185,197,67,163,216,155,50,0,181,197,143,0,175,60,59,244,108,28,219,115,67,0,0,48,59,183,231,151,231,95,24,138,90,62,174,226,251,42,190,54,20,0,79,250, +67,112,82,95,19,159,87,241,141,97,0,0,128,122,52,235,109,94,122,152,153,54,0,143,218,120,94,40,53,4,0,128,190,57,78,189,89,220,152,50,0,239,149,5,165,134,74,13,39,68,201,33,0,192,124,125,87,197,179,224,100,165,186,62,58,143,215,181,161,0,120,199,33,216, +201,218,132,82,67,0,0,184,144,210,67,71,171,3,92,162,244,108,80,106,8,0,0,67,83,122,168,76,4,160,173,220,115,193,51,100,138,148,28,2,0,204,159,210,195,102,226,66,36,150,31,126,105,40,0,247,195,240,167,32,65,211,132,82,67,0,0,232,152,210,195,102,177,54, +101,128,133,219,121,22,40,53,4,0,128,177,41,61,108,22,241,52,175,204,180,1,22,106,237,57,160,212,16,0,0,166,162,180,232,104,20,7,83,6,88,160,152,152,121,229,25,224,64,17,0,0,152,18,165,135,205,162,52,101,128,133,57,184,247,43,53,4,0,128,169,81,122,216, +60,86,166,13,176,16,27,247,252,70,113,99,202,0,0,192,112,74,139,16,189,81,0,126,36,38,239,149,26,250,224,1,0,0,147,166,244,80,73,9,192,157,43,207,5,37,233,0,0,144,130,44,248,18,223,52,214,166,13,48,83,91,247,120,165,134,0,0,144,10,189,82,154,69,76,0, +42,61,4,230,102,237,254,174,212,16,0,0,82,227,52,171,102,113,48,101,128,25,201,130,221,186,74,13,1,0,32,65,87,22,51,141,99,99,218,0,51,225,163,134,82,67,0,0,72,150,114,19,229,38,192,242,148,238,229,238,253,0,0,144,186,189,133,74,227,175,244,250,105,1, +169,202,221,199,149,26,2,0,192,28,40,61,108,30,59,211,6,72,244,126,127,116,15,87,106,8,0,0,115,145,91,180,52,142,194,180,1,18,99,71,110,243,19,110,51,211,6,0,0,166,109,107,241,210,120,161,163,167,10,144,138,141,251,182,15,23,0,0,48,71,74,81,244,211,2, +230,41,38,223,149,150,55,139,189,105,3,0,0,105,45,122,44,100,44,122,128,249,136,73,247,27,247,234,198,59,112,125,172,152,168,231,134,0,0,128,7,124,87,197,179,112,234,169,69,61,31,87,241,125,21,95,27,10,96,130,254,119,21,107,195,208,200,103,85,124,99, +24,0,0,32,61,190,230,55,15,253,180,128,169,41,220,155,27,199,214,180,1,0,128,116,233,183,210,60,98,255,49,37,42,128,251,120,218,125,17,1,0,128,196,57,17,75,63,45,32,77,250,102,217,105,11,0,0,139,118,176,192,105,28,27,211,6,24,217,206,189,216,189,27,0, +0,150,44,126,229,87,178,210,60,114,83,7,24,137,221,181,205,227,96,218,0,0,192,252,172,45,118,28,249,14,36,97,229,254,235,126,13,0,0,188,161,124,197,23,127,96,218,98,82,230,232,222,219,56,214,166,14,0,0,88,40,137,183,163,52,117,128,129,232,121,216,60, +118,166,13,0,0,204,159,82,22,253,180,128,105,42,221,107,27,71,252,72,163,212,16,0,0,44,154,68,120,127,127,150,204,212,1,122,146,187,207,182,138,149,169,3,0,0,203,114,99,33,212,56,110,76,27,160,7,89,112,18,173,114,112,0,0,192,2,170,199,216,154,58,64,199, +124,96,240,129,97,113,158,27,2,0,0,90,122,93,197,223,171,248,212,80,52,242,139,42,190,173,226,165,161,0,58,16,147,228,78,232,107,254,252,250,228,252,19,0,0,88,168,125,240,165,191,77,63,45,125,91,128,75,21,238,167,173,98,99,234,0,0,0,241,116,40,165,135, +237,202,93,156,172,5,180,181,114,239,109,21,123,83,7,0,0,184,179,182,72,106,21,59,83,7,104,33,38,195,245,205,106,183,59,214,135,4,0,0,224,45,91,139,165,86,81,152,58,64,67,74,189,219,133,94,99,0,0,192,59,236,24,104,31,250,105,1,117,149,238,153,78,152, +5,0,0,186,181,178,104,106,21,199,160,12,6,120,90,238,126,233,30,11,0,0,244,99,99,241,164,81,49,208,185,44,104,2,111,23,44,0,0,208,171,131,5,84,171,40,77,29,224,1,74,186,221,87,1,0,128,129,22,95,118,18,104,90,12,116,99,231,222,216,42,14,166,14,0,0,208, +212,218,98,170,245,177,242,202,99,128,59,202,184,219,223,75,51,211,7,0,0,104,195,174,130,118,17,75,139,52,48,6,28,180,209,62,10,211,7,0,0,104,43,38,101,142,22,86,154,196,3,173,238,159,74,183,219,197,206,244,1,0,0,46,101,135,129,102,198,64,115,154,192, +183,139,248,17,197,14,87,0,0,160,19,165,69,86,235,200,77,31,88,28,229,218,237,67,15,66,0,0,160,83,7,11,45,141,141,129,39,21,238,123,173,99,99,250,0,0,0,93,203,130,126,48,154,196,3,143,201,221,239,90,199,193,244,1,0,0,250,178,182,232,210,228,24,120,80, +22,36,253,47,217,201,42,233,191,48,207,13,1,0,0,3,250,230,188,104,211,227,164,185,56,102,223,87,241,181,161,128,217,137,201,152,63,5,229,197,109,125,118,126,190,0,0,0,244,186,112,115,122,151,38,241,192,27,123,247,182,214,177,53,125,0,0,128,161,196,221, +70,74,107,218,151,214,216,225,6,243,81,186,175,93,212,95,16,0,0,96,80,133,197,88,235,56,6,253,98,192,125,80,114,63,51,133,0,0,128,49,236,44,202,156,124,8,11,101,167,234,101,81,152,66,0,0,192,152,244,211,106,31,123,211,7,146,20,147,209,71,247,48,167,190, +2,0,0,233,202,130,93,10,22,118,176,44,18,249,74,174,1,0,128,25,88,91,164,41,189,129,133,80,106,125,89,56,20,3,0,0,152,148,173,133,154,164,22,204,220,198,189,202,125,14,0,0,152,31,101,56,151,157,248,101,231,2,76,87,225,62,165,188,26,0,0,152,167,44,232, +167,37,169,5,243,147,187,63,57,213,21,0,0,152,55,253,180,44,252,96,78,98,146,89,162,94,162,30,0,0,88,128,210,34,238,226,164,22,48,190,152,92,150,204,186,44,214,166,17,0,0,144,146,131,133,156,126,51,144,176,152,204,210,23,240,178,216,154,70,0,0,64,138, +139,65,59,27,36,181,32,85,146,89,118,154,2,0,0,11,149,91,212,93,28,27,211,8,6,183,115,239,185,184,111,150,94,128,0,0,64,210,74,139,187,139,163,48,141,96,48,91,247,156,139,35,55,141,0,0,128,57,216,91,224,89,32,66,2,10,247,154,139,163,52,141,0,0,128,185, +136,165,39,71,11,189,139,75,120,86,166,18,244,166,112,159,185,56,246,166,17,0,0,48,55,43,139,189,78,146,90,153,169,4,189,220,159,28,98,113,89,196,143,22,250,102,1,0,0,179,84,88,244,117,114,114,152,69,35,116,71,50,171,155,176,131,20,0,0,152,53,167,135, +73,106,193,84,72,102,57,184,2,0,0,160,150,152,136,185,177,0,212,171,6,220,139,102,17,59,83,9,0,0,88,10,187,34,44,36,97,76,146,89,118,139,2,0,0,180,82,88,12,74,106,193,8,36,179,28,82,193,4,60,55,4,0,0,36,234,229,121,97,249,11,67,113,145,184,219,237,251, +42,190,54,20,80,203,31,170,200,13,195,197,62,59,223,199,1,0,0,22,201,78,9,77,153,97,40,14,165,232,38,74,83,9,0,0,88,186,44,232,167,37,169,5,253,147,204,114,32,5,0,0,64,167,114,139,68,73,45,232,81,233,222,160,9,60,0,0,128,5,167,164,22,164,162,112,79,232, +172,9,252,202,116,2,0,0,120,215,222,162,177,179,176,240,4,201,44,137,114,0,0,128,1,196,82,22,77,226,237,166,128,46,20,238,3,157,197,214,116,2,0,0,120,92,76,194,104,18,47,169,5,151,40,92,255,157,197,193,116,2,0,0,168,103,109,17,41,169,5,45,21,174,251, +206,226,24,52,129,7,0,0,104,164,180,152,148,212,130,134,10,215,187,94,124,0,0,0,99,211,36,94,82,11,234,42,92,231,154,192,3,0,0,76,129,38,241,146,90,80,71,225,250,214,4,30,0,0,96,74,52,137,151,212,130,199,20,174,107,77,224,1,0,0,166,72,147,120,73,45,120, +72,225,122,238,52,226,142,88,77,224,1,0,0,58,84,90,108,118,158,212,90,155,86,36,172,112,29,75,116,3,0,0,164,64,147,120,141,159,33,4,201,172,62,66,130,27,0,0,160,39,154,196,75,106,193,214,53,219,121,108,76,43,0,0,128,126,105,18,47,169,197,114,237,92,171, +157,199,206,180,2,0,0,24,198,202,34,84,82,139,197,145,204,210,4,30,0,0,32,121,133,197,104,47,177,53,181,152,24,165,198,253,53,129,151,204,2,0,0,24,193,198,162,84,9,18,179,38,153,213,95,56,209,16,0,0,96,68,202,144,250,137,125,176,123,131,113,101,65,50, +75,121,49,0,0,192,140,237,45,80,245,215,97,86,28,254,160,172,24,0,0,96,246,148,37,245,155,212,202,76,49,6,180,14,146,89,125,238,188,4,0,0,96,66,174,44,130,123,109,30,173,223,14,67,208,23,207,142,75,0,0,128,197,81,166,36,169,69,186,244,195,235,47,142, +65,50,11,0,0,96,210,114,139,87,205,164,73,74,76,180,28,92,91,146,209,0,0,0,75,87,88,196,106,42,77,18,178,160,255,157,100,22,0,0,0,63,40,45,102,123,111,46,173,132,137,75,40,17,182,163,18,0,0,128,7,232,201,211,127,147,105,187,63,104,163,112,253,72,102, +1,0,0,240,126,122,243,244,95,210,148,155,102,52,176,117,221,244,30,59,211,12,0,0,32,109,177,44,78,143,158,254,99,99,170,81,227,90,148,96,150,204,2,0,0,160,193,66,250,104,161,59,200,66,90,95,45,30,178,114,13,14,86,6,12,0,0,192,204,22,212,26,80,15,179, +160,150,212,226,190,194,117,225,218,3,0,0,160,61,73,173,225,250,106,173,77,183,197,139,201,21,7,51,12,119,205,101,166,28,0,0,192,124,173,45,126,7,139,109,176,99,100,169,178,160,119,221,144,201,44,167,141,2,0,0,44,64,97,17,60,104,25,148,197,246,178,196, +164,177,157,144,195,133,235,11,0,0,96,65,74,11,97,167,32,226,186,74,60,10,83,14,0,0,96,121,244,247,25,54,14,65,9,226,92,197,93,66,74,12,37,179,0,0,0,24,136,164,150,134,241,92,166,52,175,37,179,0,0,0,24,86,220,49,100,103,137,134,241,52,103,87,214,56,177, +51,245,0,0,0,136,36,181,198,137,99,176,91,43,85,177,39,154,198,239,146,89,0,0,0,140,76,82,107,188,216,7,187,181,82,145,133,83,47,52,243,86,50,11,0,0,128,9,45,214,237,58,25,175,183,86,97,10,78,154,93,89,227,197,141,233,7,0,0,192,99,86,22,237,163,159,132, +152,153,134,147,146,7,187,23,199,78,102,217,193,8,0,0,192,147,36,181,198,223,173,181,49,13,71,151,5,167,128,74,102,1,0,0,144,20,73,173,105,52,141,207,77,197,81,148,230,255,36,18,187,146,89,0,0,0,52,38,169,53,157,50,196,220,116,28,68,28,231,163,57,55, +137,100,214,202,116,4,0,0,160,173,181,197,245,164,78,67,204,76,201,94,100,231,241,53,207,36,179,0,0,0,152,137,194,34,123,82,17,251,58,41,197,234,70,22,244,201,146,204,2,0,0,96,182,10,139,237,201,45,252,203,32,177,213,86,22,36,178,36,179,0,0,0,88,132, +194,162,123,146,73,128,93,80,138,88,87,22,36,178,36,179,0,0,0,88,156,194,226,123,210,165,136,153,41,250,160,85,144,200,146,204,2,0,0,96,209,10,139,112,167,34,38,224,234,60,87,111,204,9,201,44,0,0,0,8,65,82,43,133,184,57,255,158,150,214,103,235,110,55, +214,43,115,64,50,11,0,0,0,126,172,176,40,79,38,246,97,222,201,45,187,177,36,179,0,0,0,160,182,194,226,60,201,38,242,235,25,204,189,236,60,255,246,126,175,146,89,0,0,0,208,84,97,145,158,108,98,225,110,231,86,150,200,92,139,127,207,77,176,19,43,229,200, +221,50,33,132,103,134,0,0,0,38,33,38,69,118,134,33,105,183,85,124,81,197,87,85,92,87,241,122,2,127,167,44,156,18,32,63,59,255,180,179,39,93,113,62,253,166,138,23,134,2,36,180,0,0,96,74,138,32,169,53,39,47,195,41,201,245,215,123,127,126,217,227,255,95, +236,131,21,19,86,121,120,147,192,186,242,107,152,133,152,204,250,164,231,249,3,73,145,208,2,0,128,105,137,9,137,67,144,136,152,179,152,148,136,9,138,219,42,190,189,247,239,95,55,152,35,113,126,252,52,156,118,96,221,5,243,36,153,5,15,144,208,2,0,128,233, +145,212,2,162,219,42,62,15,146,89,240,14,9,45,0,0,152,38,73,45,88,182,152,196,138,59,179,94,27,10,120,215,7,134,0,0,0,44,102,1,215,63,164,68,66,11,0,0,44,106,129,233,184,118,221,195,211,36,180,0,0,96,218,98,82,235,95,130,30,58,176,4,47,130,100,22,212, +34,161,5,0,0,211,231,148,51,152,191,23,85,252,202,48,64,61,18,90,0,0,144,134,187,164,214,11,67,1,179,243,219,32,153,5,141,60,55,4,0,0,144,140,191,85,241,101,21,89,56,157,130,8,164,47,38,178,126,103,24,160,25,9,45,0,0,72,79,76,106,61,171,34,55,20,144, +172,184,235,242,215,193,174,75,104,229,153,33,0,0,128,100,21,85,236,12,3,36,71,95,60,184,144,29,90,0,0,144,174,184,24,254,54,156,118,106,125,104,56,32,153,235,54,38,179,190,49,20,208,158,29,90,0,0,144,190,216,79,235,80,197,149,161,128,73,251,34,156,122, +102,189,54,20,112,25,167,28,2,0,64,250,238,118,124,220,26,10,152,172,23,85,124,30,36,179,160,19,118,104,1,0,192,124,196,29,90,113,167,150,19,16,97,90,226,174,172,23,134,1,186,163,135,22,0,0,204,199,223,170,248,99,21,31,5,73,45,152,130,184,27,235,179, +112,42,53,4,58,36,161,5,0,0,243,18,147,90,95,86,241,125,21,159,26,14,24,205,109,56,37,179,190,54,20,208,61,37,135,0,0,48,95,121,21,251,160,89,60,12,237,174,175,157,126,89,208,19,77,225,1,0,96,190,174,207,139,234,151,134,2,6,243,162,138,159,7,201,44,232, +149,132,22,0,0,204,219,221,78,17,61,124,160,127,191,9,167,6,240,64,207,244,208,2,0,128,249,187,107,22,31,91,142,228,134,3,58,119,215,252,253,191,13,5,12,67,66,11,0,0,150,227,186,138,111,195,41,169,245,161,225,128,78,196,93,144,177,196,240,27,67,1,195, +81,114,8,0,0,203,242,34,156,74,16,111,13,5,92,236,119,65,191,44,24,133,83,14,1,0,96,153,226,201,135,241,4,196,220,80,64,99,49,129,21,251,101,189,48,20,48,14,37,135,0,0,176,76,177,175,214,239,131,190,90,208,84,44,49,252,188,138,63,27,10,24,143,29,90,0, +0,192,42,156,118,107,101,134,2,30,21,79,11,141,167,24,42,49,132,145,233,161,5,0,0,220,53,181,126,97,40,224,189,98,137,97,220,153,37,153,5,19,96,135,22,0,0,112,223,186,138,93,56,245,216,2,78,9,172,152,200,186,54,20,48,29,118,104,1,0,0,247,197,146,170, +159,91,188,195,15,215,195,191,184,30,0,0,0,32,29,101,21,255,16,98,129,241,42,156,118,43,2,19,165,228,16,0,0,120,140,134,241,44,205,117,56,53,126,191,53,20,48,93,74,14,1,0,128,199,104,24,207,82,196,94,89,177,241,251,39,65,50,11,0,0,0,102,35,150,96,197, +82,44,37,105,98,110,113,8,118,33,2,0,0,192,108,197,211,15,183,65,2,68,204,39,74,151,53,0,0,0,44,67,94,197,49,72,134,136,116,227,38,156,122,196,1,0,0,0,11,98,183,150,176,43,11,0,0,0,72,82,220,229,18,119,187,72,148,136,20,122,101,217,149,5,0,0,0,252,160, +12,18,38,98,154,17,15,51,40,92,162,0,0,0,192,67,178,112,218,5,35,137,34,166,18,177,44,246,202,165,9,0,0,0,60,165,8,167,93,49,18,42,98,204,242,194,204,165,8,0,0,0,52,17,119,197,148,65,98,69,12,27,241,244,205,181,203,15,0,0,0,184,68,86,197,46,72,180,136, +97,78,47,84,94,8,0,0,0,116,38,11,250,107,9,229,133,0,0,0,64,130,242,32,177,37,186,75,100,229,46,41,0,0,0,96,40,69,56,245,59,146,152,17,18,89,0,0,0,64,82,54,193,137,136,66,195,119,0,0,0,32,49,119,39,34,74,108,137,247,37,178,10,151,9,0,0,0,48,85,69,80, +138,40,36,178,0,0,0,128,4,21,85,220,4,73,29,137,44,0,0,0,128,196,228,193,169,136,75,106,246,94,152,242,0,0,0,192,92,228,85,236,130,164,207,220,226,213,249,247,186,50,197,1,0,0,128,185,202,194,41,1,162,129,124,218,17,203,73,139,112,58,16,0,0,0,0,96,17, +98,34,164,8,250,108,217,141,5,0,0,0,144,160,172,138,109,112,58,162,221,88,0,0,0,0,9,138,187,127,148,36,78,227,164,194,109,176,27,11,0,0,0,160,145,117,208,72,94,18,11,0,0,0,32,65,119,253,182,246,193,206,45,73,44,0,0,0,128,4,229,225,148,132,209,80,190, +125,79,172,77,56,245,46,3,24,220,51,67,0,0,0,44,92,220,189,21,75,19,127,25,78,137,174,204,144,188,227,117,21,215,85,124,121,254,121,107,72,128,49,73,104,1,0,0,188,45,150,206,229,225,77,130,107,137,39,243,189,60,199,87,247,254,12,48,25,18,90,0,0,0,143, +91,157,227,103,247,254,60,167,36,87,220,125,117,151,188,186,62,255,249,181,95,59,48,101,18,90,0,0,0,205,197,132,214,93,114,235,167,33,141,68,215,93,226,42,254,252,235,249,207,183,193,238,43,32,65,18,90,0,0,0,221,185,75,116,221,253,140,126,22,222,78,116, +229,61,253,127,223,37,171,110,171,248,246,252,243,54,188,73,100,1,204,134,132,22,0,0,192,120,238,39,190,218,184,54,132,0,0,0,0,0,48,113,31,24,2,0,0,0,0,82,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0, +0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82, +36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11, +0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0, +72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72, +104,1,0,0,0,144,20,9,45,0,0,0,0,146,34,161,5,0,0,0,64,82,36,180,0,0,0,0,72,138,132,22,0,0,0,0,73,145,208,2,0,0,0,32,41,18,90,0,0,0,0,36,69,66,11,0,0,0,128,164,72,104,1,0,0,0,144,20,9,45,0,0,0,0,146,242,255,5,24,0,142,248,78,14,98,33,228,71,0,0,0,0,73, +69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::sine_wave_png = (const char*) temp_77db788; + +//================== square_wave.png ================== +static const unsigned char temp_5a5e8e78[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,4,164,0,0,2,171,8,6,0,0,0,207,165,85,63,0,0,0,9,112,72,89,115,0,0,23,18,0,0,23,18,1,103,159,210,82,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101, +97,100,121,113,201,101,60,0,0,23,205,73,68,65,84,120,218,236,221,63,146,148,199,1,198,225,214,138,64,153,55,116,230,225,4,94,157,128,209,9,88,78,160,37,115,6,156,0,113,2,164,208,17,67,228,114,36,136,28,50,202,156,105,201,148,121,148,217,25,206,164,204, +221,254,190,45,244,7,73,32,161,151,233,238,231,169,234,98,237,64,59,221,223,4,83,191,237,238,41,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,114,222,179,4,111,221,214,18,0,192,180,46,235,120,97,25,0,0,126,158,32,245,235,156,150,37,60,157,213,113,163,142,205,58,0,0,154,22,165,46,215,241,188,142,125,29,7,203,2,0,176,16,164,94,95,139,80,231,117,220,92,255,5,0,120,19,135,58,158,212, +241,89,17,167,0,128,201,9,82,191,108,83,199,253,178,68,168,83,203,1,0,188,5,251,58,30,215,177,179,20,0,192,140,4,169,159,182,41,75,136,186,176,20,0,192,239,228,80,199,131,34,76,1,0,147,17,164,126,172,237,130,186,91,150,24,5,0,144,176,175,227,94,89,238, +156,2,0,24,222,251,150,224,123,218,37,229,207,138,59,162,0,128,172,77,29,127,41,203,31,11,247,150,3,0,24,157,29,82,47,181,93,81,15,45,3,0,240,142,237,235,184,85,150,111,234,3,0,24,146,32,181,120,84,220,21,5,0,28,143,118,116,239,118,113,132,15,0,24,148, +32,37,70,1,0,199,169,237,144,250,168,136,82,0,192,128,102,15,82,98,20,0,112,204,68,41,0,96,72,51,7,41,49,10,0,232,65,139,82,215,139,59,165,0,128,129,156,76,58,239,118,129,249,133,199,15,0,116,224,180,44,223,2,124,106,41,0,128,81,188,63,225,156,183,117, +252,205,163,7,0,58,242,199,117,60,181,20,0,192,8,102,11,82,237,47,139,255,40,254,194,8,0,244,231,172,142,231,117,124,101,41,0,128,222,205,118,100,239,126,29,27,143,29,0,232,84,187,3,211,31,214,0,128,238,205,180,67,170,253,85,113,231,145,3,0,29,251,160, +142,111,235,216,91,10,0,160,103,51,125,203,94,187,12,116,235,145,3,0,3,104,223,186,119,176,12,0,64,175,102,57,178,183,45,98,20,0,48,142,251,150,0,0,232,217,44,65,234,99,143,26,0,24,200,69,113,151,20,0,208,177,25,238,144,218,20,119,71,1,0,227,249,79,29, +255,180,12,0,64,143,102,216,33,117,238,49,3,0,3,186,99,9,0,128,94,205,16,164,28,215,3,0,70,180,41,203,183,8,3,0,116,103,244,32,229,131,26,0,48,50,59,193,1,128,46,141,30,164,182,30,49,0,48,176,27,150,0,0,232,209,232,65,202,135,52,0,96,100,91,75,0,0,244, +104,134,35,123,0,0,35,115,61,1,0,208,29,71,246,0,0,250,182,177,4,0,64,111,70,14,82,167,30,47,0,48,1,59,164,0,128,238,140,28,164,124,56,3,0,0,0,56,66,39,150,0,0,160,107,127,182,4,0,64,111,4,41,0,128,190,185,166,0,0,232,142,32,5,0,0,0,64,148,32,5,0,0,0, +64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0, +0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0, +0,0,64,148,32,5,0,0,0,64,212,53,75,48,164,123,117,92,90,6,0,38,243,176,142,51,203,0,0,112,252,4,169,49,181,24,181,183,12,0,76,230,133,37,0,0,232,131,35,123,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82, +0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68, +9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0, +0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82, +0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68, +9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0, +0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82, +0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68, +9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0, +0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82, +0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68, +9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0, +0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,9,82,0,0,0,0,68,93,179,4,0,0,0,0,223,115,90,199,217,58,218,207,127,88,127,254,174,203,58,254,91,199,97,29,123,203,246,250,4,41,0,0,0,128,82,206,235,184,81,199,182,252, +56,62,189,202,246,21,255,95,139,84,251,58,30,175,63,243,19,4,41,0,0,0,96,86,155,58,238,151,37,70,157,190,133,255,222,213,174,170,187,101,217,53,213,194,212,110,253,153,239,112,135,20,0,0,0,48,155,109,29,207,234,248,87,29,23,229,237,196,168,31,218,148, +37,118,181,223,241,104,253,223,172,4,41,0,0,0,96,22,155,58,62,47,75,140,218,6,127,239,69,121,25,166,78,61,6,65,10,0,0,0,152,67,59,70,247,101,89,142,231,189,43,23,101,9,83,231,179,63,12,65,10,0,0,0,24,89,219,145,212,118,68,61,44,199,177,59,169,189,134, +182,75,107,234,221,82,130,20,0,0,0,48,170,118,193,120,219,145,180,61,194,215,118,81,150,80,182,153,241,193,8,82,0,0,0,192,136,218,177,184,22,124,142,121,23,82,11,102,95,174,255,78,69,144,2,0,0,0,70,115,81,150,99,113,61,28,137,187,58,82,56,85,148,18,164, +0,0,0,128,145,180,176,243,168,179,215,60,93,148,18,164,0,0,0,128,81,180,160,243,172,211,215,126,117,217,249,20,23,157,11,82,0,0,0,192,8,90,200,233,253,155,235,54,101,137,82,195,19,164,0,0,0,128,17,180,24,53,194,145,183,109,29,159,140,254,176,4,41,0,0, +0,160,119,231,235,24,197,253,50,248,125,82,130,20,0,0,0,208,179,118,68,239,225,128,243,122,56,242,67,19,164,0,0,0,128,158,221,45,203,221,75,163,217,214,113,49,234,67,19,164,0,0,0,128,94,181,221,81,119,6,158,223,253,81,39,38,72,1,0,0,0,189,106,187,163, +78,7,158,223,166,12,186,75,74,144,2,0,0,0,122,117,199,28,251,36,72,1,0,0,0,61,186,40,99,239,142,186,114,86,6,252,198,61,65,10,0,0,0,232,209,205,137,230,250,241,104,19,18,164,0,0,0,128,222,180,157,81,231,19,205,119,184,185,10,82,0,0,0,64,111,182,147,205, +119,179,142,97,8,82,0,0,0,64,111,110,76,56,231,237,72,147,17,164,0,0,0,128,222,156,77,56,231,161,34,156,32,5,0,0,0,244,102,198,32,181,25,105,50,130,20,0,0,0,208,155,211,9,231,188,29,105,50,130,20,0,0,0,208,147,173,37,232,159,32,5,0,0,0,208,135,97,118, +134,9,82,0,0,0,0,125,24,230,238,44,65,10,0,0,0,128,40,65,10,0,0,0,128,40,65,10,0,0,0,128,168,145,131,212,139,137,159,235,222,91,27,0,0,0,56,86,35,7,169,75,143,23,0,0,0,224,248,140,126,100,111,198,93,82,66,28,0,0,0,112,212,70,15,82,51,198,153,131,183, +53,0,0,0,112,204,70,15,82,95,76,248,76,159,123,91,3,0,0,0,199,204,14,169,241,60,241,182,6,0,0,0,142,217,232,65,106,63,217,243,108,119,102,185,67,10,0,0,0,56,106,51,92,106,62,211,142,33,187,163,0,0,0,128,163,119,50,193,28,159,78,244,60,159,122,75,3,0, +0,0,199,110,134,32,181,43,203,78,169,209,29,138,29,82,0,0,0,64,7,78,38,153,231,103,230,8,0,0,0,112,28,102,9,82,159,150,177,119,73,181,185,237,188,157,1,0,0,128,30,204,18,164,90,176,25,121,7,209,103,101,142,99,137,0,0,0,192,0,78,38,154,235,168,187,164, +14,117,124,226,173,12,0,0,0,244,98,166,32,213,98,212,237,1,231,117,219,219,24,0,0,0,232,201,201,100,243,125,82,198,250,38,186,182,235,107,239,109,12,0,0,0,244,228,100,194,57,183,29,69,135,1,230,113,89,199,3,111,97,0,0,0,160,55,51,6,169,118,116,239,86, +233,251,62,169,171,227,135,46,50,7,0,0,0,186,115,50,233,188,219,238,162,123,29,191,254,143,214,57,0,0,0,0,116,231,100,226,185,239,74,159,23,130,183,215,44,70,1,0,0,0,221,58,153,124,254,187,210,79,148,186,58,106,184,243,182,5,0,0,0,122,118,98,9,254,31, +120,218,17,184,99,190,143,233,197,250,26,159,120,92,0,0,0,64,239,4,169,197,190,142,15,203,113,30,133,107,175,237,122,113,76,15,0,0,0,24,132,32,245,210,161,44,81,234,193,17,189,166,246,90,142,125,247,22,0,0,0,192,27,17,164,126,236,147,178,132,169,253, +59,124,13,237,119,95,95,95,11,0,0,0,192,80,4,169,87,107,199,227,218,206,164,91,37,123,84,110,191,254,222,54,14,30,3,0,0,0,48,34,65,234,231,181,75,196,219,110,169,22,136,118,191,227,239,217,149,151,33,106,111,217,1,0,0,128,145,93,179,4,175,101,191,142, +123,117,156,215,113,179,142,109,29,167,191,242,191,215,238,132,106,177,235,139,245,95,119,68,1,0,0,0,211,16,164,222,76,11,71,187,242,114,183,212,89,29,155,245,223,63,173,63,191,202,161,142,175,203,114,252,239,178,56,142,7,0,0,0,76,76,144,250,109,174, +2,211,19,75,1,0,0,0,240,122,220,33,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,212,53,75,0,0,208,181,211,58,182,150,1,128,137,156,89,130,254,9,82,0,0,253,127,40,127,102,25,0,128,158,56,178,7,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0, +0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5, +0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32,5,0,0,0,64,148,32, +5,0,0,0,64,148,32,5,0,0,0,208,135,253,40,19,17,164,0,128,81,188,176,4,0,0,125,16,164,0,128,81,60,183,4,0,192,192,14,35,77,70,144,2,0,124,72,3,0,240,89,39,74,144,2,0,70,113,105,9,0,128,129,125,49,210,100,4,41,0,96,20,45,72,185,71,10,0,24,249,179,206,48, +4,41,0,96,36,123,75,0,0,248,156,115,252,4,41,0,96,36,79,45,1,0,48,160,39,101,176,157,224,130,20,0,48,218,135,53,0,128,209,12,247,71,55,65,10,0,24,73,251,203,225,206,50,0,0,131,125,190,25,238,143,110,130,20,0,48,154,199,150,0,0,24,200,112,199,245,154, +247,60,87,0,96,64,207,234,216,90,6,0,96,0,215,235,56,140,54,41,59,164,0,128,17,61,176,4,0,192,0,118,101,192,24,213,216,33,5,0,140,202,46,41,0,160,119,67,238,142,106,236,144,2,0,70,117,207,18,0,0,29,107,59,190,15,163,78,238,125,207,23,0,24,212,191,203, +178,27,124,107,41,0,128,206,28,234,184,93,199,55,163,78,208,145,61,0,96,116,95,214,113,102,25,0,128,142,124,88,199,229,200,19,116,100,15,0,24,221,173,50,224,87,37,3,0,195,106,215,14,92,142,62,73,65,10,0,24,221,161,44,81,10,0,224,216,237,234,248,116,134, +137,186,67,10,0,152,193,161,142,175,235,56,183,20,0,192,145,218,149,229,222,168,41,8,82,0,192,44,218,214,119,81,10,0,56,70,187,50,81,140,106,4,41,0,96,38,87,81,106,91,199,7,150,3,0,56,2,187,50,89,140,106,124,203,30,0,48,163,246,173,123,159,215,177,177, +20,0,192,59,212,46,48,255,116,198,137,11,82,0,192,172,78,235,120,84,28,225,3,0,242,14,101,249,210,149,203,89,23,192,183,236,1,0,179,122,177,126,16,188,181,254,12,0,144,208,118,68,125,88,38,142,81,141,59,164,0,128,217,125,85,199,95,235,248,182,44,71,249, +220,45,5,0,252,30,246,117,124,84,199,223,235,248,102,246,197,112,100,15,0,224,165,118,140,239,110,29,119,214,159,1,0,126,171,93,29,143,203,18,164,88,9,82,0,0,175,118,81,199,205,226,142,41,0,224,205,181,227,120,45,66,61,41,203,125,81,252,128,32,5,0,240, +203,182,235,184,81,150,99,125,118,79,1,0,223,181,47,75,132,122,190,254,124,176,36,63,79,144,2,0,248,117,132,41,0,160,69,40,95,142,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,14,253,79,128,1,0,153,2,27,8,33,213,49,244,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::square_wave_png = (const char*) temp_5a5e8e78; + +//================== triangle_wave.png ================== +static const unsigned char temp_d696456d[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,4,172,0,0,2,113,8,6,0,0,0,111,215,42,130,0,0,0,9,112,72,89,115,0,0,23,18,0,0,23,18,1,103,159,210,82,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101, +97,100,121,113,201,101,60,0,0,32,173,73,68,65,84,120,218,236,221,251,145,85,199,122,198,225,214,113,2,100,224,9,129,12,204,201,128,16,94,101,64,8,100,160,16,80,6,132,128,28,1,114,4,216,17,72,25,224,189,197,12,12,48,151,125,89,151,175,187,159,167,170, +171,252,199,41,219,181,46,189,250,251,157,13,180,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,206,126,113,9,0,190,122,113,88,47,15,235,230,118,61, +228,239,195,250,243,176,254,247,118,1,0,0,0,192,98,142,129,42,135,245,238,176,62,29,214,231,51,215,95,135,245,254,176,222,180,199,3,23,0,0,0,0,60,43,237,75,104,250,188,240,250,216,190,196,171,23,46,49,0,0,0,0,207,57,70,164,183,237,203,175,162,62,111, +176,142,191,218,186,113,217,1,0,0,0,120,200,241,87,79,91,133,170,31,215,111,205,47,174,0,0,0,0,184,117,252,11,212,143,127,76,239,243,206,235,24,203,94,187,29,0,0,0,0,115,123,219,246,15,85,63,174,227,223,155,229,215,86,0,0,0,0,147,57,6,161,53,254,66,245, +37,255,98,246,151,110,19,0,0,0,192,28,142,177,170,194,31,1,60,229,143,8,138,86,0,0,0,0,131,235,37,86,137,86,0,0,0,0,19,232,45,86,137,86,0,0,0,0,3,235,53,86,137,86,0,0,0,0,3,234,61,86,137,86,0,0,0,0,3,25,37,86,137,86,0,0,0,0,3,24,45,86,137,86,0,0,0,0, +29,27,53,86,137,86,0,0,0,0,29,26,61,86,137,86,0,0,0,0,29,153,37,86,137,86,0,0,0,0,29,152,45,86,137,86,0,0,0,0,133,205,26,171,68,43,0,0,0,128,130,102,143,85,162,21,0,0,0,64,33,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136, +85,162,21,0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136,85,162,21,0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136,85,162,21,0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37, +90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136,85,162,21,0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136,85,162,21,0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136,85,162,21, +0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,0,0,0,0,101,136,85,162,21,0,0,0,64,25,98,149,104,5,0,0,0,80,134,88,37,90,1,0,0,0,148,33,86,137,86,162,21,0,0,0,80,134,88,101,137,86,0,0,192,230,126,113,9,128,71,28,99,213,135,38, +84,240,197,223,135,245,239,195,250,211,165,0,0,0,214,38,88,1,15,17,171,120,136,104,5,0,0,108,66,176,2,126,36,86,241,20,209,10,0,0,88,157,96,5,220,39,86,113,10,209,10,0,0,88,149,96,5,220,17,171,56,135,104,5,0,0,172,70,176,2,142,196,42,46,33,90,1,0,0,171, +16,172,0,177,138,107,136,86,0,0,192,226,4,43,152,155,88,197,18,68,43,0,0,96,81,130,21,204,75,172,98,73,162,21,0,0,176,24,193,10,230,36,86,177,6,209,10,0,0,88,132,96,5,243,17,171,88,147,104,5,0,0,92,77,176,130,185,136,85,108,65,180,2,0,0,174,34,88,193, +60,196,42,182,36,90,1,0,0,23,19,172,96,14,98,21,123,16,173,0,0,128,139,8,86,48,62,177,138,61,137,86,0,0,192,217,4,43,24,155,88,69,5,162,21,0,0,112,22,193,10,198,37,86,81,137,104,5,0,0,156,76,176,130,49,137,85,84,36,90,1,0,0,39,17,172,96,60,98,21,149, +137,86,0,0,192,179,4,43,24,139,88,69,15,68,43,0,0,224,73,130,21,140,67,172,162,39,162,21,0,0,240,40,193,10,198,32,86,209,35,209,10,0,0,120,144,96,5,253,19,171,232,153,104,5,0,0,252,228,95,46,1,116,77,172,90,223,239,135,245,171,203,224,25,6,0,0,0,78,27, +244,63,30,214,103,107,181,245,238,222,245,142,235,177,234,250,171,137,86,0,0,0,208,53,177,106,219,88,117,39,174,139,104,5,0,0,0,252,76,172,218,39,86,221,137,235,35,90,1,0,0,0,223,136,85,251,198,170,59,113,157,68,43,0,0,0,64,172,170,18,171,238,196,245, +18,173,0,0,0,96,102,98,85,173,88,117,39,174,155,104,5,0,0,0,51,18,171,106,198,170,59,113,253,68,43,0,0,0,152,137,88,85,59,86,221,137,235,40,90,1,0,0,192,12,196,170,62,98,213,157,184,158,162,21,0,0,0,140,76,172,234,43,86,221,137,235,42,90,1,0,0,192,136, +196,170,62,99,213,157,184,190,162,21,0,0,0,140,68,172,234,59,86,221,137,235,44,90,1,0,0,192,8,196,170,49,98,213,157,184,222,162,21,0,0,0,244,76,172,26,43,86,221,137,235,46,90,1,0,0,64,143,196,170,49,99,213,157,184,254,162,21,0,0,0,244,68,172,26,59,86, +221,137,251,32,90,1,0,0,64,15,196,170,57,98,213,157,184,31,162,21,0,0,0,84,38,86,205,21,171,238,196,125,17,173,0,0,0,160,34,177,106,206,88,117,39,238,143,104,5,0,0,0,149,136,85,115,199,170,59,113,159,68,43,0,0,0,168,64,172,18,171,238,139,251,37,90,1, +0,0,192,158,196,42,177,234,33,113,223,68,43,0,0,0,216,131,88,37,86,61,37,238,159,104,5,0,0,0,91,18,171,196,170,83,196,125,20,173,0,0,0,96,11,98,149,88,117,142,184,159,162,21,0,0,0,172,73,172,18,171,46,17,247,85,180,2,0,0,128,53,136,85,98,213,53,226,254, +138,86,0,0,0,176,36,177,74,172,90,66,220,103,209,10,0,0,0,150,32,86,137,85,75,138,251,45,90,1,0,0,192,53,196,42,177,106,13,113,223,69,43,0,0,0,184,132,88,37,86,173,41,238,191,104,5,0,0,0,231,16,171,196,170,45,196,115,32,90,1,0,0,192,41,196,42,177,106, +75,241,60,136,86,0,0,0,240,20,177,74,172,218,67,60,23,162,21,0,0,0,60,68,172,18,171,246,20,207,135,104,5,0,0,0,247,137,85,98,85,5,241,156,136,86,0,0,0,112,36,86,137,85,149,196,243,34,90,1,0,0,48,55,177,74,172,170,40,158,27,209,10,0,0,128,57,137,85,98, +85,101,241,252,136,86,0,0,0,204,69,172,18,171,122,16,207,145,104,5,0,0,192,28,196,42,177,170,39,241,60,137,86,0,0,0,140,77,172,18,171,122,20,207,149,104,5,0,0,192,152,196,42,177,170,103,241,124,137,86,0,0,0,140,69,172,18,171,70,16,207,153,104,5,0,0,192, +24,196,42,177,106,36,241,188,137,86,0,0,0,244,77,172,18,171,70,20,207,157,104,5,0,0,64,159,196,42,177,106,100,241,252,137,86,0,0,0,244,69,172,18,171,102,16,207,161,104,5,0,0,64,31,196,42,177,106,38,241,60,138,86,0,0,0,212,38,86,137,85,51,138,231,82,180, +2,0,0,160,38,177,74,172,154,89,60,159,162,21,0,0,0,181,136,85,98,21,162,149,104,5,0,0,64,25,98,149,88,197,55,241,188,138,86,0,0,0,236,75,172,18,171,248,89,60,183,162,21,0,0,0,251,16,171,196,42,30,23,207,175,104,5,0,0,192,182,196,42,177,138,231,197,115, +44,90,1,0,0,176,13,177,74,172,226,116,241,60,139,86,0,0,0,172,75,172,18,171,56,95,60,215,162,21,0,0,0,235,16,171,196,42,46,23,207,183,104,5,0,0,192,178,196,42,177,138,235,197,115,46,90,1,0,0,176,12,177,74,172,98,57,241,188,139,86,0,0,0,92,71,172,18,171, +88,94,60,247,162,21,0,0,0,151,17,171,196,42,214,19,207,191,104,5,0,0,192,121,196,42,177,138,245,197,123,32,90,1,0,0,112,26,177,74,172,98,59,241,62,136,86,0,0,0,60,77,172,18,171,216,94,188,23,162,21,0,0,0,15,19,171,196,42,246,19,239,135,104,5,0,0,192, +247,196,42,177,138,253,197,123,34,90,1,0,0,240,133,88,37,86,81,71,188,47,162,21,0,0,192,236,196,42,177,138,122,226,189,17,173,0,0,0,102,37,86,137,85,212,21,239,143,104,5,0,0,48,27,177,74,172,162,190,120,143,68,43,0,0,128,89,136,85,98,21,253,136,247,73, +180,2,0,0,24,157,88,37,86,209,159,120,175,68,43,0,0,128,81,137,85,98,21,253,138,247,75,180,2,0,0,24,141,88,37,86,209,191,120,207,68,43,0,0,128,81,136,85,98,21,227,136,247,77,180,2,0,0,232,157,88,37,86,49,158,120,239,68,43,0,0,128,94,137,85,98,21,227, +138,247,79,180,2,0,0,232,141,88,37,86,49,190,120,15,69,43,0,0,128,94,136,85,98,21,243,136,247,81,180,2,0,0,168,78,172,18,171,152,79,188,151,162,21,0,0,64,85,98,149,88,197,188,226,253,20,173,0,0,0,170,17,171,196,42,136,247,84,180,2,0,0,168,66,172,18,171, +224,78,188,175,162,21,0,0,192,222,196,42,177,10,126,20,239,173,104,5,0,0,176,23,177,74,172,130,199,196,251,43,90,1,0,0,108,77,172,18,171,224,57,241,30,139,86,0,0,0,91,17,171,196,42,56,85,188,207,162,21,0,0,192,218,196,42,177,10,206,21,239,181,104,5,0, +0,176,22,177,74,172,130,75,197,251,45,90,1,0,0,44,77,172,18,171,224,90,241,158,139,86,0,0,0,75,17,171,196,42,88,74,188,239,162,21,0,0,192,181,196,42,177,10,150,22,239,189,104,5,0,0,112,41,177,74,172,130,181,196,251,47,90,1,0,0,156,75,172,18,171,96,109, +177,15,136,86,0,0,0,167,18,171,196,42,216,74,236,7,162,21,0,0,192,115,196,42,177,10,182,22,251,130,104,5,0,0,240,24,177,74,172,130,189,196,254,32,90,1,0,0,252,72,172,18,171,96,111,177,79,136,86,0,0,0,119,196,42,177,10,170,136,253,66,180,2,0,0,16,171, +196,42,168,38,246,13,209,10,0,0,152,151,88,37,86,65,85,177,127,136,86,0,0,192,124,196,42,177,10,170,139,125,68,180,2,0,0,230,33,86,137,85,208,139,216,79,68,43,0,0,96,124,98,149,88,5,189,137,125,69,180,2,0,0,198,37,86,137,85,208,171,216,95,68,43,0,0,96, +60,98,149,88,5,189,139,125,70,180,2,0,0,198,33,86,137,85,48,138,216,111,68,43,0,0,160,127,98,149,88,5,163,137,125,71,180,2,0,0,250,37,86,137,85,48,170,216,127,68,43,0,0,160,63,98,149,88,5,163,139,125,72,180,2,0,0,250,33,86,137,85,48,139,216,143,68,43, +0,0,160,62,177,74,172,130,217,196,190,36,90,1,0,0,117,137,85,98,21,204,42,246,39,209,10,0,0,168,71,172,18,171,96,118,177,79,137,86,0,0,64,29,98,149,88,5,124,17,251,149,104,5,0,0,236,79,172,18,171,128,239,197,190,37,90,1,0,0,251,17,171,196,42,224,97,177, +127,137,86,0,0,192,246,196,42,177,10,120,90,236,99,162,21,0,0,176,29,177,74,172,2,78,19,251,153,104,5,0,0,172,79,172,18,171,128,243,196,190,38,90,1,0,0,235,17,171,196,42,224,50,177,191,137,86,0,0,192,242,196,42,177,10,184,78,236,115,162,21,0,0,176,28, +177,74,172,2,150,17,251,157,104,5,0,0,92,79,172,18,171,128,101,197,190,39,90,1,0,0,151,19,171,196,42,96,29,177,255,137,86,0,0,192,249,196,42,177,10,88,87,236,131,162,21,0,0,112,58,177,74,172,2,182,17,251,161,104,5,0,0,60,79,172,18,171,128,109,197,190, +40,90,1,0,0,143,19,171,196,42,96,31,177,63,138,86,0,0,192,207,196,42,177,10,216,87,236,147,162,21,0,0,240,141,88,37,86,1,53,196,126,41,90,1,0,0,98,149,88,5,84,19,251,166,104,5,0,0,51,19,171,196,42,160,166,216,63,69,43,0,0,152,145,88,37,86,1,181,197,62, +42,90,1,0,192,76,196,42,177,10,232,67,236,167,162,21,0,0,204,64,172,18,171,128,190,196,190,42,90,1,0,192,200,196,42,177,10,232,83,236,175,162,21,0,0,140,72,172,18,171,128,190,197,62,43,90,1,0,192,72,196,42,177,10,24,67,236,183,162,21,0,0,140,64,172,18, +171,128,177,196,190,43,90,1,0,64,207,196,42,177,10,24,83,236,191,162,21,0,0,244,72,172,18,171,128,177,197,62,44,90,1,0,64,79,196,42,177,10,152,67,236,199,162,21,0,0,244,64,172,18,171,128,185,196,190,44,90,1,0,64,101,98,149,88,5,204,41,246,103,209,10, +0,0,42,18,171,196,42,96,110,177,79,139,86,0,0,80,137,88,37,86,1,28,197,126,45,90,1,0,64,5,98,149,88,5,112,95,236,219,162,21,0,0,236,73,172,18,171,0,30,18,251,183,104,5,0,0,123,16,171,196,42,128,167,196,62,46,90,1,0,192,150,196,42,177,10,224,20,177,159, +139,86,0,0,176,5,177,74,172,2,56,71,236,235,162,21,0,0,172,73,172,18,171,0,46,17,251,187,104,5,0,0,107,16,171,196,42,128,107,196,62,47,90,1,0,192,146,196,42,177,10,96,9,177,223,139,86,0,0,176,4,177,74,172,2,88,82,236,251,162,21,0,0,92,67,172,18,171,0, +214,16,251,191,104,5,0,0,151,16,171,196,42,128,53,197,119,64,180,2,0,128,115,136,85,98,21,192,22,226,123,32,90,1,0,192,41,196,42,177,10,96,75,241,93,16,173,0,0,224,41,98,149,88,5,176,135,248,62,136,86,0,0,240,16,177,74,172,2,216,83,124,39,68,43,0,0,184, +79,172,18,171,0,42,136,239,133,104,5,0,0,71,98,149,88,5,80,73,124,55,68,43,0,0,230,38,86,137,85,0,21,197,247,67,180,2,0,96,78,98,149,88,5,80,89,124,71,68,43,0,0,230,34,86,137,85,0,61,136,239,137,104,5,0,192,28,196,42,177,10,160,39,241,93,17,173,0,0,24, +155,88,37,86,1,244,40,190,47,162,21,0,0,99,18,171,196,42,128,158,197,119,70,180,2,0,96,44,98,149,88,5,48,130,248,222,136,86,0,0,140,65,172,18,171,0,70,18,223,29,209,10,0,128,190,137,85,98,21,192,136,226,251,35,90,1,0,208,39,177,74,172,2,24,89,124,135, +68,43,0,0,250,34,86,137,85,0,51,136,239,145,104,5,0,64,31,196,42,177,10,96,38,241,93,18,173,0,128,39,29,191,229,175,110,23,236,66,172,18,171,0,102,20,223,39,209,10,0,38,119,115,123,38,250,237,176,62,220,126,191,159,251,190,127,184,157,113,227,91,207, +154,196,42,177,10,96,102,241,157,18,173,0,96,50,55,237,75,160,250,180,208,247,254,211,237,255,62,223,124,22,35,86,137,85,0,136,86,162,21,0,204,115,230,249,176,242,119,255,211,237,255,29,184,152,88,37,86,1,240,253,1,206,183,75,180,2,128,81,207,57,75,253, +154,74,184,98,85,98,149,88,5,192,195,135,57,223,48,209,10,0,70,113,252,238,174,253,139,170,231,214,177,61,188,114,43,56,133,88,37,86,1,240,184,248,142,137,86,0,48,128,55,197,206,0,191,185,37,60,69,172,18,171,0,120,94,124,207,68,43,0,232,120,238,223,251, +87,85,79,253,218,234,198,45,226,161,135,86,172,18,171,0,56,77,124,215,68,43,0,232,204,203,14,230,126,103,0,190,35,86,137,85,0,156,47,190,111,14,172,0,208,137,151,183,223,86,103,0,186,33,86,137,85,0,92,46,190,115,14,172,0,80,92,79,177,202,25,128,175,222, +59,12,139,85,0,92,37,190,119,14,172,0,80,84,143,177,202,25,128,246,214,33,88,172,2,96,17,241,221,115,96,5,128,98,122,142,85,247,207,0,47,220,202,249,30,92,7,96,177,10,128,229,196,247,79,180,2,0,177,106,241,245,193,237,156,139,191,183,74,172,2,96,121, +241,29,20,173,0,64,172,90,124,189,113,91,231,240,214,129,87,172,2,64,180,18,173,0,64,172,234,104,221,184,189,99,123,49,240,195,43,86,1,32,90,137,86,0,32,86,141,185,252,209,192,193,189,117,200,21,171,0,16,173,68,43,0,16,171,58,92,175,220,234,49,249,117, +149,88,5,128,104,37,90,1,128,88,229,87,86,56,52,139,85,0,248,254,250,102,138,86,0,32,86,53,191,178,226,17,254,101,64,177,10,0,209,74,180,2,0,177,202,44,78,25,55,14,179,94,16,0,68,43,209,10,0,196,170,1,214,11,143,192,56,222,56,200,138,85,0,136,86,162, +21,0,136,85,3,172,120,12,198,241,222,33,86,172,2,64,180,18,173,0,64,172,50,155,83,137,7,218,11,1,128,104,37,90,1,128,88,53,202,183,158,1,220,120,152,197,42,0,68,43,209,10,0,196,170,129,214,141,199,162,127,175,60,200,98,21,0,162,149,104,5,0,98,213,64, +235,181,71,227,155,127,117,252,112,115,153,223,15,235,87,151,1,0,223,153,46,29,255,5,161,15,206,66,0,116,236,229,237,183,204,191,138,247,240,181,225,86,175,193,202,131,109,136,0,192,247,102,86,162,21,0,189,18,171,158,246,159,46,193,55,255,114,9,12,15, +0,224,187,211,29,209,10,128,222,136,85,207,187,113,9,190,17,172,12,13,0,224,251,211,39,209,10,128,94,136,85,156,77,176,50,44,0,128,239,80,191,68,43,0,170,19,171,184,136,96,101,72,0,0,223,163,190,137,86,0,84,37,86,113,49,193,202,112,0,0,190,75,253,19, +173,0,168,70,172,226,42,130,149,161,0,0,124,159,198,32,90,1,80,133,88,197,180,94,29,214,103,235,193,245,206,227,1,64,113,241,189,94,117,253,213,68,43,0,246,243,242,246,91,228,155,124,254,122,239,241,249,166,215,95,88,253,237,214,61,232,247,230,191,185, +6,192,247,106,118,126,105,5,192,94,252,178,234,58,255,227,18,140,65,125,245,203,42,0,250,22,223,111,191,180,2,96,24,126,89,117,253,138,199,104,12,31,60,204,98,21,0,162,149,37,90,1,32,86,13,178,124,179,7,241,214,195,44,86,1,32,90,89,162,21,0,98,213,32, +139,129,94,10,177,10,0,68,43,75,180,2,64,172,242,23,174,83,202,39,177,10,0,68,43,75,180,2,64,172,234,124,189,241,72,141,229,173,88,5,0,162,149,37,90,1,32,86,117,190,110,60,86,99,185,17,171,0,64,180,178,68,43,0,196,170,230,143,3,82,204,59,177,10,0,68, +43,75,180,2,64,172,234,116,189,246,104,141,233,70,172,2,0,209,202,18,173,0,16,171,58,92,159,60,90,99,27,253,87,86,98,21,0,162,149,37,90,1,32,86,141,183,226,241,26,219,139,129,95,30,177,10,0,209,202,97,86,180,2,64,172,26,111,125,244,120,205,225,141,88, +5,0,162,149,37,90,1,32,86,117,178,94,121,196,230,241,94,172,2,128,97,197,193,86,180,2,64,172,26,100,253,230,17,155,203,241,143,6,126,18,171,0,96,88,113,192,21,173,0,16,171,90,255,127,20,240,133,199,204,139,37,86,1,192,88,226,160,43,90,1,96,166,246,157, +165,215,23,76,172,2,128,113,197,129,215,97,26,128,85,102,105,177,202,191,10,200,6,7,217,158,94,52,177,10,0,206,255,214,59,248,138,86,0,44,67,172,18,171,240,194,253,180,222,186,85,0,112,145,56,252,138,86,0,76,51,59,139,85,12,247,226,125,44,124,8,244,208, +2,192,117,226,16,44,90,1,112,213,204,44,86,137,85,236,228,248,183,239,191,47,246,192,126,116,248,3,128,197,196,97,88,180,2,224,108,98,149,88,69,17,175,139,188,140,111,221,10,0,88,92,28,138,69,43,0,78,38,86,137,85,20,115,252,181,213,219,157,94,204,15, +135,117,227,22,0,192,106,226,112,44,90,1,240,44,177,74,172,162,176,155,182,93,184,58,254,113,196,87,46,57,0,108,34,14,201,162,21,0,143,18,171,196,42,58,241,226,246,97,90,250,239,184,250,212,190,4,177,27,151,24,0,54,23,135,101,209,10,128,159,136,85,98, +21,157,186,139,87,239,218,249,255,178,224,49,80,29,163,215,155,38,82,1,64,5,113,104,22,173,0,248,74,172,18,171,186,242,139,75,240,172,155,246,45,64,29,95,240,23,183,255,243,31,247,254,51,127,184,76,0,80,210,241,224,248,206,101,88,205,223,135,245,239, +195,250,211,165,0,40,237,56,203,126,184,55,207,178,188,95,15,235,119,151,1,0,128,83,165,249,111,124,253,210,10,96,94,126,89,229,151,85,0,0,20,21,135,105,209,10,96,66,98,149,88,5,0,64,113,113,168,22,173,0,38,34,86,137,85,0,0,116,34,14,215,162,21,192,4, +196,42,177,10,0,128,206,196,33,91,180,2,24,152,88,37,86,1,0,208,169,56,108,139,86,0,3,18,171,196,42,0,0,58,23,135,110,209,10,96,32,98,149,88,5,0,192,32,226,240,45,90,1,12,64,172,18,171,0,0,24,76,28,194,69,43,128,142,137,85,98,21,0,0,131,138,195,184,104, +5,208,33,177,74,172,2,0,96,112,113,40,23,173,0,58,34,86,137,85,0,0,76,34,14,231,162,21,64,7,196,42,177,10,0,128,201,196,33,93,180,2,40,76,172,18,171,0,0,152,84,28,214,69,43,128,130,196,42,177,10,0,128,201,197,161,93,180,2,40,68,172,18,171,0,0,224,31, +113,120,23,173,0,10,16,171,196,42,0,0,248,78,28,226,69,43,128,29,137,85,98,21,0,0,60,40,14,243,162,21,192,14,196,42,177,10,0,0,158,20,135,122,209,10,96,67,98,149,88,5,0,0,39,137,195,189,104,5,176,1,177,74,172,2,0,128,179,196,33,95,180,2,88,145,88,37, +86,1,0,192,69,226,176,47,90,1,172,64,172,18,171,0,0,224,42,113,232,23,173,0,22,36,86,137,85,0,0,176,136,56,252,139,86,0,11,16,171,196,42,0,0,88,84,12,1,162,21,192,21,196,42,177,10,0,0,86,17,195,128,104,5,112,1,177,74,172,2,0,128,85,197,80,32,90,1,156, +65,172,18,171,0,0,96,19,49,28,136,86,0,39,16,171,196,42,0,0,216,84,12,9,162,21,192,19,196,42,177,10,0,0,118,17,195,130,104,5,240,0,177,74,172,2,0,128,93,197,208,32,90,1,220,35,86,137,85,0,0,80,66,12,15,162,21,64,19,171,196,42,0,0,40,38,134,8,209,10,152, +154,88,37,86,1,0,64,73,49,76,136,86,192,148,196,42,177,10,0,0,74,139,161,66,180,2,166,34,86,137,85,0,0,208,133,24,46,68,43,96,10,98,149,88,5,0,0,93,137,33,67,180,2,134,38,86,137,85,0,0,208,165,24,54,68,43,96,72,98,149,88,5,0,0,93,139,161,67,180,2,134, +34,86,137,85,0,0,48,132,24,62,68,43,96,8,98,149,88,5,0,0,67,137,33,68,180,2,186,38,86,137,85,0,0,48,164,24,70,68,43,160,75,98,149,88,5,0,0,67,139,161,68,180,2,186,34,86,137,85,0,0,48,133,24,78,68,43,160,11,98,149,88,5,0,0,83,137,33,69,180,2,74,19,171, +196,42,0,0,152,82,12,43,162,21,80,146,88,37,86,1,0,192,212,98,104,17,173,128,82,196,42,177,10,0,0,104,162,149,104,5,84,33,86,137,85,0,0,192,61,49,196,136,86,192,174,196,42,177,10,0,0,120,64,12,51,162,21,176,11,177,74,172,2,0,0,158,16,67,141,104,5,108, +74,172,18,171,0,0,128,19,196,112,35,90,1,155,16,171,196,42,0,0,224,12,49,228,136,86,192,170,196,42,177,10,0,0,184,64,12,59,162,21,176,10,177,74,172,2,0,0,174,16,67,143,104,5,44,74,172,18,171,0,0,128,5,196,240,35,90,1,139,16,171,196,42,0,0,96,65,49,4, +137,86,192,85,196,42,177,10,0,0,88,65,12,67,162,21,112,17,177,74,172,2,0,0,86,20,67,145,104,5,156,69,172,18,171,0,0,128,13,196,112,36,90,1,39,17,171,196,42,0,0,96,67,49,36,137,86,192,147,196,42,177,10,0,0,216,65,12,75,162,21,240,32,177,74,172,2,0,0,118, +20,67,147,104,5,124,71,172,18,171,0,0,128,2,98,120,18,173,128,127,136,85,98,21,0,0,80,72,12,81,162,21,76,78,172,18,171,0,0,128,130,98,152,18,173,96,82,98,149,88,5,0,0,20,22,67,149,104,5,147,17,171,196,42,0,0,160,3,49,92,137,86,48,9,177,74,172,2,0,0,58, +18,67,150,104,5,131,19,171,196,42,0,0,160,67,49,108,137,86,48,40,177,74,172,2,0,0,58,22,67,151,104,5,131,17,171,196,42,0,0,96,0,49,124,137,86,48,8,177,74,172,2,0,0,6,18,67,152,104,5,157,19,171,196,42,0,0,96,64,49,140,137,86,208,41,177,74,172,2,0,0,6, +22,67,153,104,5,157,17,171,196,42,0,0,96,2,49,156,137,86,208,9,177,74,172,2,0,0,38,18,67,154,104,5,197,137,85,98,21,0,0,48,161,24,214,68,43,40,74,172,18,171,0,0,128,137,197,208,38,90,65,49,98,149,88,5,0,0,32,90,53,209,10,170,16,171,196,42,0,0,128,175, +98,136,19,173,96,103,98,149,88,5,0,0,240,147,24,230,68,43,216,137,88,37,86,1,0,0,60,42,134,58,209,10,54,38,86,137,85,0,0,0,207,138,225,78,180,130,141,136,85,98,21,0,0,192,201,98,200,19,173,96,101,98,149,88,5,0,0,112,182,24,246,68,43,88,137,88,37,86,1, +0,0,92,44,134,62,209,10,22,38,86,137,85,0,0,0,87,139,225,79,180,130,133,136,85,98,21,0,0,192,98,98,8,20,173,224,74,98,149,88,5,0,0,176,184,24,6,69,43,184,144,88,37,86,1,0,0,172,38,134,66,209,10,206,36,86,137,85,0,0,0,171,139,225,80,180,130,19,137,85, +98,21,0,0,192,102,98,72,20,173,224,25,98,149,88,5,0,0,176,185,24,22,69,43,120,132,88,37,86,1,0,0,236,38,134,70,209,10,126,32,86,137,85,0,0,0,187,139,225,81,180,130,91,98,149,88,5,0,0,80,70,12,145,162,21,211,19,171,196,42,0,0,128,114,98,152,20,173,152, +150,88,37,86,1,0,0,148,21,67,165,104,197,116,196,42,177,10,0,0,160,188,24,46,69,43,166,33,86,137,85,0,0,0,221,136,33,83,180,98,120,98,149,88,5,0,0,208,157,24,54,69,43,134,37,86,137,85,0,0,0,221,138,161,83,180,98,56,98,149,88,5,0,0,208,189,24,62,69,43, +134,33,86,137,85,0,0,0,195,136,33,84,180,162,123,98,149,88,5,0,0,48,156,24,70,69,43,186,37,86,137,85,0,0,0,195,138,161,84,180,162,59,98,149,88,5,0,0,48,188,24,78,69,43,186,33,86,137,85,0,0,0,211,136,33,85,180,162,60,177,74,172,2,0,0,152,78,12,171,162, +21,101,137,85,98,21,0,0,192,180,98,104,21,173,40,71,172,18,171,0,0,0,166,23,195,171,104,69,25,98,149,88,5,0,0,192,173,24,98,69,43,118,39,86,137,85,0,0,0,252,32,134,89,209,138,221,136,85,98,21,0,0,0,143,136,161,86,180,98,115,98,149,88,5,0,0,192,51,98, +184,21,173,216,140,88,37,86,1,0,0,112,162,24,114,69,43,86,39,86,137,85,0,0,0,156,41,134,93,209,138,213,136,85,98,21,0,0,0,23,138,161,87,180,98,113,98,149,88,5,0,0,192,149,98,248,21,173,88,140,88,37,86,1,0,0,176,144,24,130,69,43,174,38,86,137,85,0,0,0, +44,44,134,97,209,138,139,137,85,98,21,0,0,0,43,137,161,88,180,226,108,98,149,88,5,0,0,192,202,98,56,22,173,56,153,88,37,86,1,0,0,176,145,24,146,69,43,158,37,86,137,85,0,0,0,108,44,134,101,209,138,71,137,85,98,21,0,0,0,59,137,161,89,180,226,39,98,149, +88,5,0,0,192,206,98,120,22,173,248,74,172,18,171,0,0,0,40,34,134,104,209,10,177,170,137,85,0,0,0,20,19,195,180,104,53,49,177,74,172,2,0,0,160,168,24,170,69,171,9,137,85,98,21,0,0,0,197,197,112,45,90,77,68,172,18,171,0,0,0,232,68,12,217,162,213,4,196, +42,177,10,0,0,128,206,196,176,45,90,13,76,172,18,171,0,0,0,232,84,12,221,162,213,128,196,42,177,10,0,0,128,206,197,240,45,90,13,68,172,18,171,0,0,0,24,68,12,225,162,213,0,196,42,177,10,0,0,128,193,196,48,46,90,117,76,172,18,171,0,0,0,24,84,12,229,162, +85,135,196,42,177,10,0,0,128,193,197,112,46,90,117,68,172,18,171,0,0,0,152,68,12,233,162,85,7,196,42,177,10,0,0,128,201,196,176,46,90,21,38,86,137,85,0,0,0,76,42,134,118,209,170,32,177,74,172,2,0,0,96,114,49,188,139,86,133,136,85,98,21,0,0,0,252,35,134, +120,209,170,0,177,74,172,2,0,0,128,239,196,48,47,90,237,72,172,18,171,0,0,0,224,65,49,212,139,86,59,16,171,196,42,0,0,0,120,82,12,247,162,213,134,196,42,177,10,0,0,0,78,18,67,190,104,181,1,177,74,172,2,0,0,128,179,196,176,47,90,173,72,172,18,171,0,0, +0,224,34,49,244,139,86,43,16,171,196,42,0,0,0,184,74,12,255,162,213,130,196,42,177,10,0,0,0,22,17,17,64,180,90,128,88,37,86,1,0,0,192,162,34,6,136,86,87,16,171,196,42,0,0,0,88,69,68,1,209,234,2,98,149,88,5,0,0,0,171,138,56,32,90,157,65,172,18,171,0,0, +0,96,19,17,9,68,171,19,136,85,98,21,0,0,0,108,42,98,129,104,245,4,177,74,172,2,0,0,128,93,68,52,16,173,30,32,86,137,85,0,0,0,176,171,136,7,162,213,61,98,149,88,5,0,0,0,37,68,68,16,173,154,88,37,86,1,0,0,64,49,17,19,166,142,86,98,149,88,5,0,0,0,37,69, +84,152,50,90,137,85,98,21,0,0,0,148,22,113,97,170,104,37,86,137,85,0,0,0,208,133,136,12,83,68,43,177,74,172,2,0,0,128,174,68,108,24,58,90,137,85,98,21,0,0,0,116,41,162,195,144,209,74,172,18,171,0,0,0,160,107,17,31,134,138,86,98,149,88,5,0,0,0,67,136, +8,49,68,180,18,171,196,42,0,0,0,24,74,196,136,174,163,149,88,37,86,1,0,0,192,144,34,74,116,25,173,196,42,177,10,0,0,0,134,22,113,162,171,104,37,86,137,85,0,0,0,48,133,136,20,93,68,43,177,74,172,2,0,0,128,169,68,172,40,29,173,196,42,177,10,0,0,0,166,20, +209,162,100,180,18,171,196,42,0,0,0,152,90,196,139,82,209,74,172,18,171,0,0,0,128,38,90,85,137,86,98,149,88,5,0,0,0,220,147,38,102,236,25,173,196,42,177,10,0,0,0,120,64,154,168,177,71,180,18,171,196,42,0,0,0,224,9,105,226,198,150,209,74,172,18,171,0, +0,0,128,19,164,137,28,91,68,43,177,74,172,2,0,0,0,206,144,38,118,172,29,173,196,42,177,10,0,0,0,56,83,154,232,97,137,85,192,192,254,195,37,0,0,128,238,252,121,88,255,119,88,175,93,10,58,242,235,97,253,238,50,0,167,16,172,0,0,160,79,162,21,61,17,171,128, +179,8,86,0,0,208,47,209,138,30,136,85,192,217,4,43,0,0,232,155,104,69,101,98,21,112,17,193,10,0,0,250,39,90,81,145,88,5,92,76,176,2,0,128,49,136,86,84,34,86,1,0,0,0,95,229,176,62,91,214,142,43,94,67,0,0,0,224,71,105,162,137,37,86,1,0,0,0,197,164,137, +39,150,88,5,0,0,0,20,147,38,162,88,98,21,0,0,0,80,76,154,152,98,137,85,0,0,0,64,49,105,162,138,37,86,1,0,0,0,197,164,137,43,150,88,5,0,0,0,20,147,38,178,88,98,21,0,0,0,80,76,154,216,98,137,85,0,0,0,64,49,105,162,139,37,86,1,0,0,0,197,164,137,47,150,88, +5,0,0,0,20,147,38,194,88,98,21,0,0,0,80,76,154,24,99,137,85,0,0,0,64,49,105,162,140,37,86,1,0,0,0,197,164,137,51,150,88,5,0,0,0,20,147,38,210,88,98,21,0,0,0,80,76,154,88,35,86,1,0,0,0,20,147,38,218,136,85,0,0,0,0,197,164,137,55,98,21,0,0,0,64,49,105, +34,142,88,5,0,0,0,80,76,154,152,35,86,1,0,0,0,20,147,38,234,136,85,0,0,0,0,197,164,137,59,98,21,0,0,0,64,49,105,34,143,88,5,0,0,0,80,76,154,216,35,86,1,0,0,0,20,147,38,250,136,85,0,0,0,0,197,164,137,63,98,21,0,0,0,64,49,105,34,144,88,5,0,0,0,80,76,154, +24,36,86,1,0,0,0,20,147,38,10,137,85,0,0,0,0,197,164,137,67,98,21,0,0,0,64,49,105,34,145,88,5,0,0,0,80,76,154,88,36,86,1,0,0,0,20,147,38,26,137,85,0,0,0,0,197,164,137,71,98,21,0,0,0,64,49,105,34,146,88,5,0,0,0,80,76,154,152,36,86,1,0,0,0,20,147,38,42, +137,85,0,0,0,0,197,164,137,75,98,21,0,0,0,64,49,105,34,147,88,5,0,0,0,80,76,154,216,36,86,1,0,0,0,20,147,38,58,137,85,0,0,0,0,197,164,137,79,98,21,0,0,0,64,49,105,34,148,88,5,0,0,0,80,76,154,24,37,86,1,0,0,0,20,147,38,74,137,85,0,0,0,0,197,164,137,83, +98,21,0,0,0,64,49,105,34,149,88,5,0,0,0,80,76,154,88,21,143,1,0,0,0,64,45,105,98,21,0,0,0,0,197,164,137,85,0,0,0,0,20,147,38,86,1,0,0,0,80,76,154,88,5,0,0,0,64,49,105,98,21,0,0,0,0,197,164,137,85,0,0,0,0,20,147,38,86,1,0,0,0,80,76,154,88,5,0,0,0,64,49, +105,98,21,0,0,0,0,197,164,137,85,0,0,0,0,20,147,38,86,1,0,0,0,80,204,203,195,250,171,213,13,85,199,255,223,226,54,1,0,0,0,204,229,230,176,62,182,122,177,234,83,251,18,212,0,0,0,0,152,212,219,86,39,86,253,118,88,47,220,18,0,0,0,0,142,191,104,250,208,246, +253,85,213,43,183,1,0,0,0,128,31,189,110,95,226,209,150,161,42,46,59,0,0,0,0,207,121,117,88,239,219,122,161,234,248,107,174,184,204,0,0,0,0,156,235,248,247,73,165,125,137,87,215,254,171,130,199,72,245,166,125,249,203,222,1,88,193,47,46,1,0,0,48,161,151, +183,235,230,176,254,235,153,255,236,127,31,214,223,135,245,231,97,253,225,210,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,239,255,5,24,0,2,125,7,137,153,101,243,194,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* BinaryData::triangle_wave_png = (const char*) temp_d696456d; + //================== wifi.png ================== static const unsigned char temp_43e5b62e[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,1,64,0,0,0,247,8,6,0,0,0,108,40,141,211,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101, diff --git a/JuceLibraryCode/BinaryData.h b/JuceLibraryCode/BinaryData.h index d811f05d43fe17554b9690e2e075e8cebac80de0..891b5212ef6e86f2ee78e96af85b23d6545cc68a 100644 --- a/JuceLibraryCode/BinaryData.h +++ b/JuceLibraryCode/BinaryData.h @@ -46,6 +46,81 @@ namespace BinaryData extern const char* silkscreen_ttf; const int silkscreen_ttfSize = 18336; + extern const char* RadioButtons01_png; + const int RadioButtons01_pngSize = 818; + + extern const char* RadioButtons02_png; + const int RadioButtons02_pngSize = 824; + + extern const char* RadioButtons03_png; + const int RadioButtons03_pngSize = 704; + + extern const char* RadioButtons04_png; + const int RadioButtons04_pngSize = 792; + + extern const char* RadioButtons05_png; + const int RadioButtons05_pngSize = 942; + + extern const char* RadioButtons_neutral01_png; + const int RadioButtons_neutral01_pngSize = 730; + + extern const char* RadioButtons_neutral02_png; + const int RadioButtons_neutral02_pngSize = 681; + + extern const char* RadioButtons_neutral03_png; + const int RadioButtons_neutral03_pngSize = 536; + + extern const char* RadioButtons_neutral04_png; + const int RadioButtons_neutral04_pngSize = 654; + + extern const char* RadioButtons_neutral05_png; + const int RadioButtons_neutral05_pngSize = 821; + + extern const char* RadioButtons_selected01_png; + const int RadioButtons_selected01_pngSize = 761; + + extern const char* RadioButtons_selected02_png; + const int RadioButtons_selected02_pngSize = 729; + + extern const char* RadioButtons_selected03_png; + const int RadioButtons_selected03_pngSize = 561; + + extern const char* RadioButtons_selected04_png; + const int RadioButtons_selected04_pngSize = 727; + + extern const char* RadioButtons_selected05_png; + const int RadioButtons_selected05_pngSize = 869; + + extern const char* RadioButtons_selected_over01_png; + const int RadioButtons_selected_over01_pngSize = 866; + + extern const char* RadioButtons_selected_over02_png; + const int RadioButtons_selected_over02_pngSize = 843; + + extern const char* RadioButtons_selected_over03_png; + const int RadioButtons_selected_over03_pngSize = 728; + + extern const char* RadioButtons_selected_over04_png; + const int RadioButtons_selected_over04_pngSize = 838; + + extern const char* RadioButtons_selected_over05_png; + const int RadioButtons_selected_over05_pngSize = 977; + + extern const char* noise_wave_png; + const int noise_wave_pngSize = 19800; + + extern const char* saw_wave_png; + const int saw_wave_pngSize = 10801; + + extern const char* sine_wave_png; + const int sine_wave_pngSize = 12863; + + extern const char* square_wave_png; + const int square_wave_pngSize = 6208; + + extern const char* triangle_wave_png; + const int triangle_wave_pngSize = 8480; + extern const char* wifi_png; const int wifi_pngSize = 3412; diff --git a/JuceLibraryCode/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/JuceLibraryCode/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index dbc9a72515c59cfdb60c1757f001f4eb9d191c1e..07b58308d8881df465225b0d3f95717668120385 100755 --- a/JuceLibraryCode/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/JuceLibraryCode/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -323,7 +323,7 @@ const Colour LookAndFeel::findColour (const int colourId) const throw() if (index >= 0) return colours [index]; - jassertfalse; + //jassertfalse; return Colours::black; } diff --git a/Resources/Images/Icons/RadioButtons-01.png b/Resources/Images/Icons/RadioButtons-01.png new file mode 100644 index 0000000000000000000000000000000000000000..c50f3baedbb32bbbaacf2d51699be465c6d9e5a1 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons-01.png differ diff --git a/Resources/Images/Icons/RadioButtons-02.png b/Resources/Images/Icons/RadioButtons-02.png new file mode 100644 index 0000000000000000000000000000000000000000..76348bea6c93c0dd4b82713f4ed6fa3ae681f2ee Binary files /dev/null and b/Resources/Images/Icons/RadioButtons-02.png differ diff --git a/Resources/Images/Icons/RadioButtons-03.png b/Resources/Images/Icons/RadioButtons-03.png new file mode 100644 index 0000000000000000000000000000000000000000..7974f07ac0325bd633b0b0c48867702da4145859 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons-03.png differ diff --git a/Resources/Images/Icons/RadioButtons-04.png b/Resources/Images/Icons/RadioButtons-04.png new file mode 100644 index 0000000000000000000000000000000000000000..e431c90ed86833d9cce9e7848a494a9d42a24906 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons-04.png differ diff --git a/Resources/Images/Icons/RadioButtons-05.png b/Resources/Images/Icons/RadioButtons-05.png new file mode 100644 index 0000000000000000000000000000000000000000..db8ae6e6adf855ba3d02d98b5d94a53c82e444f6 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons-05.png differ diff --git a/Resources/Images/Icons/RadioButtons_neutral-01.png b/Resources/Images/Icons/RadioButtons_neutral-01.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4738da8aff468fe392bf56b7d325bab1d42c92 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_neutral-01.png differ diff --git a/Resources/Images/Icons/RadioButtons_neutral-02.png b/Resources/Images/Icons/RadioButtons_neutral-02.png new file mode 100644 index 0000000000000000000000000000000000000000..e2426a7f3740247ec1b7df8c142406c4a11de65f Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_neutral-02.png differ diff --git a/Resources/Images/Icons/RadioButtons_neutral-03.png b/Resources/Images/Icons/RadioButtons_neutral-03.png new file mode 100644 index 0000000000000000000000000000000000000000..e130a8e5928edc92a56c511ad324d1f7449ec0ff Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_neutral-03.png differ diff --git a/Resources/Images/Icons/RadioButtons_neutral-04.png b/Resources/Images/Icons/RadioButtons_neutral-04.png new file mode 100644 index 0000000000000000000000000000000000000000..584cdb75e5c910874cfe612394426f2e1f3e0275 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_neutral-04.png differ diff --git a/Resources/Images/Icons/RadioButtons_neutral-05.png b/Resources/Images/Icons/RadioButtons_neutral-05.png new file mode 100644 index 0000000000000000000000000000000000000000..79f59c74ce3beb09cf080115a5c5b4f98ff2cd88 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_neutral-05.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected-01.png b/Resources/Images/Icons/RadioButtons_selected-01.png new file mode 100644 index 0000000000000000000000000000000000000000..a2638b271b558747cbf9981e4575925f35583b8c Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected-01.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected-02.png b/Resources/Images/Icons/RadioButtons_selected-02.png new file mode 100644 index 0000000000000000000000000000000000000000..6153bcb5150b44b97ab47fb6eb775df8a94e2791 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected-02.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected-03.png b/Resources/Images/Icons/RadioButtons_selected-03.png new file mode 100644 index 0000000000000000000000000000000000000000..9ed1e7ba021340fbd4463b8dbc4c6730f2a3c1a9 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected-03.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected-04.png b/Resources/Images/Icons/RadioButtons_selected-04.png new file mode 100644 index 0000000000000000000000000000000000000000..da4e6739bcbb479b5cdb209e17ad03862d265b08 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected-04.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected-05.png b/Resources/Images/Icons/RadioButtons_selected-05.png new file mode 100644 index 0000000000000000000000000000000000000000..c43e401f0661087e752959e006418d3f6bc9c1b9 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected-05.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected_over-01.png b/Resources/Images/Icons/RadioButtons_selected_over-01.png new file mode 100644 index 0000000000000000000000000000000000000000..1f6634a242e6c4db6213729ec55fda6d0cbe1e64 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected_over-01.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected_over-02.png b/Resources/Images/Icons/RadioButtons_selected_over-02.png new file mode 100644 index 0000000000000000000000000000000000000000..836d50993d2f9241c2f8d6d7a41fbd425376d093 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected_over-02.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected_over-03.png b/Resources/Images/Icons/RadioButtons_selected_over-03.png new file mode 100644 index 0000000000000000000000000000000000000000..20cbdfdff27a2d873f28c19aa27ddef5ebe87fe6 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected_over-03.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected_over-04.png b/Resources/Images/Icons/RadioButtons_selected_over-04.png new file mode 100644 index 0000000000000000000000000000000000000000..b1eedc7d2b81f9257106461c2e2f50f532cde9bf Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected_over-04.png differ diff --git a/Resources/Images/Icons/RadioButtons_selected_over-05.png b/Resources/Images/Icons/RadioButtons_selected_over-05.png new file mode 100644 index 0000000000000000000000000000000000000000..b57027d3c16b3c005f9c74dd965c07ddd1467fa4 Binary files /dev/null and b/Resources/Images/Icons/RadioButtons_selected_over-05.png differ diff --git a/Resources/Images/Icons/noise_wave.png b/Resources/Images/Icons/noise_wave.png new file mode 100644 index 0000000000000000000000000000000000000000..59e59bdedc317b077dbcfd3988bafd29e725c690 Binary files /dev/null and b/Resources/Images/Icons/noise_wave.png differ diff --git a/Resources/Images/Icons/saw_wave.png b/Resources/Images/Icons/saw_wave.png new file mode 100644 index 0000000000000000000000000000000000000000..38bdada85a159b0a39208d60be5283daf6f70314 Binary files /dev/null and b/Resources/Images/Icons/saw_wave.png differ diff --git a/Resources/Images/Icons/sine_wave.png b/Resources/Images/Icons/sine_wave.png new file mode 100644 index 0000000000000000000000000000000000000000..3eec7a0f53fb080fc0965ed93039d91f3b9f1de0 Binary files /dev/null and b/Resources/Images/Icons/sine_wave.png differ diff --git a/Resources/Images/Icons/square_wave.png b/Resources/Images/Icons/square_wave.png new file mode 100644 index 0000000000000000000000000000000000000000..eb06b269386aa0a4742f466883fe049e21fd460c Binary files /dev/null and b/Resources/Images/Icons/square_wave.png differ diff --git a/Resources/Images/Icons/triangle_wave.png b/Resources/Images/Icons/triangle_wave.png new file mode 100644 index 0000000000000000000000000000000000000000..179713b3f3a41a3b027e5d6f03624c570b8f1e62 Binary files /dev/null and b/Resources/Images/Icons/triangle_wave.png differ diff --git a/Source/AccessClass.cpp b/Source/AccessClass.cpp index 7816f8245e9f56d42ae9bcfcf9bd2d50f17e59b5..bf3e615725cf68b4c7686e84fb53db431668af93 100644 --- a/Source/AccessClass.cpp +++ b/Source/AccessClass.cpp @@ -1,11 +1,24 @@ -/* - ============================================================================== + /* + ------------------------------------------------------------------ - AccessClass.cpp - Created: 1 Mar 2012 1:36:31pm - Author: jsiegle + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. - ============================================================================== */ #include "AccessClass.h" @@ -14,7 +27,6 @@ #include "UI/EditorViewport.h" #include "UI/ProcessorList.h" #include "UI/DataViewport.h" -#include "UI/Configuration.h" #include "UI/ControlPanel.h" #include "UI/MessageCenter.h" #include "Audio/AudioComponent.h" @@ -22,6 +34,7 @@ void AccessClass::setUIComponent(UIComponent* ui_) { + ui = ui_; ev = ui->getEditorViewport(); @@ -30,7 +43,6 @@ void AccessClass::setUIComponent(UIComponent* ui_) pg = ui->getProcessorGraph(); cp = ui->getControlPanel(); mc = ui->getMessageCenter(); - cf = ui->getConfiguration(); ac = ui->getAudioComponent(); addActionListener(mc); diff --git a/Source/AccessClass.h b/Source/AccessClass.h index 582112bdbafa3e731d00ce7669e1c8c0ef860edf..566d1a00d34e1b6b9a4bf96f90998911384f3ecd 100644 --- a/Source/AccessClass.h +++ b/Source/AccessClass.h @@ -1,11 +1,24 @@ /* - ============================================================================== + ------------------------------------------------------------------ - AccessClass.h - Created: 1 Mar 2012 1:17:45pm - Author: jsiegle + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. - ============================================================================== */ #ifndef __ACCESSCLASS_H_CE1DC2DE__ @@ -20,9 +33,17 @@ class DataViewport; class ProcessorGraph; class MessageCenter; class ControlPanel; -class Configuration; class AudioComponent; + +/** + + Allows subclasses to access important pointers within the application. + + @see UIComponent + +*/ + class AccessClass : public ActionBroadcaster { public: @@ -39,7 +60,6 @@ public: ControlPanel* getControlPanel() {return cp;} MessageCenter* getMessageCenter() {return mc;} UIComponent* getUIComponent() {return ui;} - Configuration* getConfiguration() {return cf;} AudioComponent* getAudioComponent() {return ac;} private: @@ -51,7 +71,6 @@ private: ProcessorGraph* pg; ControlPanel* cp; MessageCenter* mc; - Configuration* cf; AudioComponent* ac; }; diff --git a/Source/Audio/AudioComponent.cpp b/Source/Audio/AudioComponent.cpp index 93119a912623e550a9c05661d94aca078fa920c1..9942ff1476a20e2e480247cdf180fb32eea5118c 100644 --- a/Source/Audio/AudioComponent.cpp +++ b/Source/Audio/AudioComponent.cpp @@ -70,6 +70,9 @@ AudioComponent::AudioComponent() : isPlaying(false) graphPlayer = new AudioProcessorPlayer(); + stopDevice(); // reduces the amount of background processing when + // device is not in use + } AudioComponent::~AudioComponent() { @@ -99,8 +102,22 @@ bool AudioComponent::callbacksAreActive() { return isPlaying; } +void AudioComponent::restartDevice() +{ + deviceManager.restartLastAudioDevice(); + +} + +void AudioComponent::stopDevice() +{ + + deviceManager.closeAudioDevice(); +} + void AudioComponent::beginCallbacks() { + restartDevice(); + std::cout << std::endl << "Adding audio callback." << std::endl; deviceManager.addAudioCallback(graphPlayer); isPlaying = true; @@ -113,5 +130,7 @@ void AudioComponent::endCallbacks() { deviceManager.removeAudioCallback(graphPlayer); isPlaying = false; + stopDevice(); + } diff --git a/Source/Audio/AudioComponent.h b/Source/Audio/AudioComponent.h index 45a804c4b88d84518d889a8a9b7c5a1a1f57acd6..e129564e6060014139eca8d14b446cd8705c5e1c 100644 --- a/Source/Audio/AudioComponent.h +++ b/Source/Audio/AudioComponent.h @@ -56,6 +56,9 @@ public: bool callbacksAreActive(); + void restartDevice(); + void stopDevice(); + AudioDeviceManager deviceManager; private: diff --git a/Source/Main.cpp b/Source/Main.cpp index f70d622a995eaca5bbef5742a2a17e69a36bcf58..68b8d21ee9466d4ac51a8619724331a3bbe54e69 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -57,11 +57,7 @@ public: LookAndFeel::setDefaultLookAndFeel(customLookAndFeel); } - void shutdown() - { - mainWindow = 0; - customLookAndFeel = 0; - } + void shutdown() { } //============================================================================== void systemRequestedQuit() diff --git a/Source/MainWindow.cpp b/Source/MainWindow.cpp index d234bf00336fdf02d08944fc4ae42470daa3ba81..f741aa3d61105c921ff3859a65dbbe026d9f35a5 100644 --- a/Source/MainWindow.cpp +++ b/Source/MainWindow.cpp @@ -31,20 +31,22 @@ MainWindow::MainWindow() Colour(Colours::black), DocumentWindow::allButtons) { - //centreWithSize (500, 400); + setResizable (true, // isResizable false); // useBottomCornerRisizer -- doesn't work very well - + // centreWithSize(500,400); + // Constraining the window's size doesn't seem to work: //setResizeLimits(500, 400, 10000, 10000); // Create ProcessorGraph and AudioComponent, and connect them. // Callbacks will be set by the play button in the control panel - processorGraph = new ProcessorGraph(); - audioComponent = new AudioComponent(); - audioComponent->connectToProcessorGraph(processorGraph); - setContentComponent (new UIComponent(this, processorGraph, audioComponent), true, true); + processorGraph = new ProcessorGraph(); + audioComponent = new AudioComponent(); + audioComponent->connectToProcessorGraph(processorGraph); + + setContentComponent (new UIComponent(this, processorGraph, audioComponent), true, true); // commandManager.registerAllCommandsForTarget (getContentComponent()); // commandManager.registerAllCommandsForTarget (JUCEApplication::getInstance()); @@ -61,16 +63,16 @@ MainWindow::MainWindow() MainWindow::~MainWindow() { - saveWindowBounds(); - processorGraph->saveState(); + saveWindowBounds(); + processorGraph->saveState(); - audioComponent->disconnectProcessorGraph(); + audioComponent->disconnectProcessorGraph(); deleteAndZero(processorGraph); deleteAndZero(audioComponent); - setContentComponent (0); - setMenuBar(0); + setContentComponent (0); + // setMenuBar(0); } diff --git a/Source/Processors/AudioNode.cpp b/Source/Processors/AudioNode.cpp index 0952a10817cb9e60dad869df627730ace251129b..5cede137287c4457cdf398f2c6c6f1918d6a58fb 100644 --- a/Source/Processors/AudioNode.cpp +++ b/Source/Processors/AudioNode.cpp @@ -25,29 +25,38 @@ #include "AudioNode.h" AudioNode::AudioNode() - : GenericProcessor("Audio Node"), volume(5.0f) + : GenericProcessor("Audio Node"), volume(5.0f), audioEditor(0) { + settings.numInputs = 64; + settings.numOutputs = 2; + // 64 inputs, 2 outputs (left and right channel) - setPlayConfigDetails(64,2,44100.0,128); + setPlayConfigDetails(getNumInputs(),getNumOutputs(),44100.0,128); leftChan.add(0); rightChan.add(1); + + currentChannel = 0; + + } AudioNode::~AudioNode() { + + } AudioProcessorEditor* AudioNode::createEditor() { - AudioEditor* editor = new AudioEditor(this); + audioEditor = new AudioEditor(this); - setEditor(editor); + //setEditor(editor); - return editor; + return audioEditor; } @@ -65,6 +74,16 @@ void AudioNode::process(AudioSampleBuffer &buffer, int& nSamples) { + // if (currentChannel == 0) + // { + // buffer.clear(1,0,buffer.getNumSamples()); + // buffer.copyFrom(); + // } else if (currentChannel == 1) + // { + // buffer.clear(0,0,buffer.getNumSamples()); + // buffer.copyFrom(); + // } else { + buffer.clear(0,0,buffer.getNumSamples()); buffer.clear(1,0,buffer.getNumSamples()); @@ -89,4 +108,5 @@ void AudioNode::process(AudioSampleBuffer &buffer, volume // gain to apply ); } + //} } diff --git a/Source/Processors/AudioNode.h b/Source/Processors/AudioNode.h index ad8c07ef5a5b57d3e1bb69689cd41524302063da..9e19c2eb938e7312cfd442e625efe4dd2ce8d9cb 100644 --- a/Source/Processors/AudioNode.h +++ b/Source/Processors/AudioNode.h @@ -41,6 +41,8 @@ */ +class AudioEditor; + class AudioNode : public GenericProcessor { public: @@ -53,6 +55,10 @@ public: void setParameter (int parameterIndex, float newValue); AudioProcessorEditor* createEditor(); + + // AudioEditor* getEditor() {return audioEditor;} + + ScopedPointer<AudioEditor> audioEditor; private: diff --git a/Source/Processors/DataThreads/DataBuffer.h b/Source/Processors/DataThreads/DataBuffer.h index 2695ab61d314e6ebe38189f3c9d550bcf34e4886..dc088a63000497d09f14bce680bf50c5db12b7f8 100644 --- a/Source/Processors/DataThreads/DataBuffer.h +++ b/Source/Processors/DataThreads/DataBuffer.h @@ -28,6 +28,9 @@ private: AbstractFifo abstractFifo; AudioSampleBuffer buffer; int numChans; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DataBuffer); + }; diff --git a/Source/Processors/DataThreads/DataThread.cpp b/Source/Processors/DataThreads/DataThread.cpp index a10c258dd7bd21d25339efbba1e28245187e2ee5..dd83b847c237fe7672fceedc8ffd7da0d43e3e2f 100644 --- a/Source/Processors/DataThreads/DataThread.cpp +++ b/Source/Processors/DataThreads/DataThread.cpp @@ -31,7 +31,10 @@ DataThread::DataThread(SourceNode* s) : Thread ("Data Thread"), dataBuffer(0) setPriority(10); } -DataThread::~DataThread() {} +DataThread::~DataThread() +{ + deleteAndZero(dataBuffer); +} void DataThread::run() { diff --git a/Source/Processors/DataThreads/DataThread.h b/Source/Processors/DataThreads/DataThread.h index a86cfa4e266065ad5aea5de7bb57c21770e5ad0d..001bb8e5fabc36645a5ea8c49a8792ebdf8b9448 100644 --- a/Source/Processors/DataThreads/DataThread.h +++ b/Source/Processors/DataThreads/DataThread.h @@ -64,6 +64,11 @@ public: SourceNode* sn; +private: + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DataThread); + + }; diff --git a/Source/Processors/DataThreads/FileReaderThread.cpp b/Source/Processors/DataThreads/FileReaderThread.cpp index ba6c1574082c28294d475db273136dcdc9de4c63..f7f1aa4ee0908735d105622ec797489e90b91f79 100644 --- a/Source/Processors/DataThreads/FileReaderThread.cpp +++ b/Source/Processors/DataThreads/FileReaderThread.cpp @@ -33,6 +33,8 @@ FileReaderThread::FileReaderThread(SourceNode* sn) : DataThread(sn), File file = File("./data_stream_16ch"); input = file.createInputStream(); + // lengthOfInputFile = file + dataBuffer = new DataBuffer(16, 4096); std::cout << "File Reader Thread initialized." << std::endl; @@ -65,12 +67,16 @@ bool FileReaderThread::updateBuffer() while (dataBuffer->getNumSamples() < 4096) { + // if (input->getTotalLength()) + + //input->read(thisSample, 4*) + for (int ch = 0; ch < numChannels; ch++) { if (input->isExhausted()) input->setPosition(0); - thisSample[ch%numChannels] = float(input->readShort()); + thisSample[ch%numChannels] = float(input->readShort())/80000.0f; } diff --git a/Source/Processors/DataThreads/FileReaderThread.h b/Source/Processors/DataThreads/FileReaderThread.h index 4e625fe1bc1eb8d1946300d336fc7d9107ef0e90..d7ac4beb8c2a1e90c6ae9e4026ea358ef21372b4 100644 --- a/Source/Processors/DataThreads/FileReaderThread.h +++ b/Source/Processors/DataThreads/FileReaderThread.h @@ -62,9 +62,14 @@ private: int numChannels; int samplesPerBlock; + int lengthOfInputFile; + + int playHead; + FileInputStream* input; float thisSample[16]; + float readBuffer[1600]; bool updateBuffer(); diff --git a/Source/Processors/Editors/AudioEditor.cpp b/Source/Processors/Editors/AudioEditor.cpp index 50f6591776d0861cc8a077bfd4488e388958ddea..808226e56e2adf0d19b1697e25047fe4da7fa2d4 100644 --- a/Source/Processors/Editors/AudioEditor.cpp +++ b/Source/Processors/Editors/AudioEditor.cpp @@ -136,16 +136,23 @@ void AudioEditor::buttonClicked(Button* button) { if (acw == 0) { - AudioComponent* ac = getAudioComponent(); - - if (ac != 0) - acw = new AudioConfigurationWindow(ac->deviceManager, (Button*) audioWindowButton); + // AudioComponent* audioComponent = getAudioComponent(); + // audioComponent->restartDevice(); + // if (audioComponent != 0) { + acw = new AudioConfigurationWindow(getAudioComponent()->deviceManager, (Button*) audioWindowButton); + acw->setUIComponent(getUIComponent()); + //} } + getAudioComponent()->restartDevice(); acw->setVisible(true); + } else { + acw->setVisible(false); + //deleteAndZero(acw); + getAudioComponent()->stopDevice(); } } @@ -205,6 +212,7 @@ AudioConfigurationWindow::~AudioConfigurationWindow() void AudioConfigurationWindow::closeButtonPressed() { controlButton->setToggleState(false,false); + getAudioComponent()->stopDevice(); setVisible(false); } diff --git a/Source/Processors/Editors/AudioEditor.h b/Source/Processors/Editors/AudioEditor.h index fcdad65b524c20185352fc63cc4e283277b4a531..5389a25d8c2da7efd5237e47aabdb5d8b852532c 100644 --- a/Source/Processors/Editors/AudioEditor.h +++ b/Source/Processors/Editors/AudioEditor.h @@ -48,7 +48,8 @@ class AudioWindowButton : public Button Font font; }; -class AudioConfigurationWindow : public DocumentWindow +class AudioConfigurationWindow : public DocumentWindow, + public AccessClass { public: AudioConfigurationWindow(AudioDeviceManager& adm, Button* b); diff --git a/Source/Processors/Editors/EventNodeEditor.cpp b/Source/Processors/Editors/EventNodeEditor.cpp index 11d68a5b52ba4b85f197154d4692f48400f03533..36173b5e580869cb128511e388adfd21f23f7e84 100644 --- a/Source/Processors/Editors/EventNodeEditor.cpp +++ b/Source/Processors/Editors/EventNodeEditor.cpp @@ -39,15 +39,15 @@ EventNodeEditor::EventNodeEditor (GenericProcessor* parentNode) createRadioButtons(35, 65, 160, hzValues, "Event frequency"); - for (int n = 0; n < getNumChildComponents(); n++) - { - Button* c = (Button*) getChildComponent(n); + // for (int n = 0; n < getNumChildComponents(); n++) + // { + // Button* c = (Button*) getChildComponent(n); - if (c->isVisible()) - c->addListener(this); + // if (c->isVisible()) + // c->addListener(this); - c->setVisible(true); - } + // c->setVisible(true); + // } } @@ -66,7 +66,7 @@ EventNodeEditor::~EventNodeEditor() // } -void EventNodeEditor::buttonClicked (Button* button) +void EventNodeEditor::buttonEvent (Button* button) { //std::cout << button->getRadioGroupId() << " " << button->getName() << std::endl; String value = button->getName(); diff --git a/Source/Processors/Editors/EventNodeEditor.h b/Source/Processors/Editors/EventNodeEditor.h index a8eada7865534895b34b97c9990ff77c83480055..dc4bc09007c1e61ace467c64e22752b88b97d1f1 100644 --- a/Source/Processors/Editors/EventNodeEditor.h +++ b/Source/Processors/Editors/EventNodeEditor.h @@ -30,13 +30,12 @@ class FilterViewport; -class EventNodeEditor : public GenericEditor//, - // public Button::Listener +class EventNodeEditor : public GenericEditor { public: EventNodeEditor (GenericProcessor* parentNode); virtual ~EventNodeEditor(); - void buttonClicked(Button* button); + void buttonEvent(Button* button); private: diff --git a/Source/Processors/Editors/FilterEditor.cpp b/Source/Processors/Editors/FilterEditor.cpp index e4c84b42fc338c34d87a2fa599a33f706977ba56..449d53126369705554d1c3830ac26358c907ea1e 100644 --- a/Source/Processors/Editors/FilterEditor.cpp +++ b/Source/Processors/Editors/FilterEditor.cpp @@ -75,11 +75,11 @@ FilterEditor::~FilterEditor() // } -void FilterEditor::buttonClicked (Button* button) +void FilterEditor::buttonEvent (Button* button) { //std::cout << button->getRadioGroupId() << " " << button->getName() << std::endl; - if (!checkDrawerButton(button) && !checkChannelSelectors(button)) { + //if (!checkDrawerButton(button) && !checkChannelSelectors(button)) { String value = button->getName(); float val; @@ -102,6 +102,6 @@ void FilterEditor::buttonClicked (Button* button) } //std::cout << button->getRadioGroupId() << " " << val << std::endl; - } + // } } \ No newline at end of file diff --git a/Source/Processors/Editors/FilterEditor.h b/Source/Processors/Editors/FilterEditor.h index ff4f336aeb4d3ddfe089e9a90382434b63302ab6..018e616f6d9d6bef6314d041a05746bf2337ef5f 100644 --- a/Source/Processors/Editors/FilterEditor.h +++ b/Source/Processors/Editors/FilterEditor.h @@ -31,18 +31,13 @@ class FilterViewport; class FilterEditor : public GenericEditor - // public Button::Listener { public: FilterEditor (GenericProcessor* parentNode); virtual ~FilterEditor(); - //void sliderValueChanged (Slider* slider); - void buttonClicked(Button* button); + void buttonEvent(Button* button); private: - //Slider* lowSlider; - //Slider* highSlider; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterEditor); diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp index 1bca25ccacd7216850e8389b87d5e4d760f778c3..b44d1a867730a11b928a94a7508b85522308e4ad 100644 --- a/Source/Processors/Editors/GenericEditor.cpp +++ b/Source/Processors/Editors/GenericEditor.cpp @@ -23,8 +23,11 @@ #include "GenericEditor.h" +#include "../ProcessorGraph.h" +#include "../RecordNode.h" +#include "../../UI/ProcessorList.h" + #include "../../UI/EditorViewport.h" -#include "../../UI/Configuration.h" #include <math.h> @@ -70,24 +73,19 @@ GenericEditor::GenericEditor (GenericProcessor* owner)//, FilterViewport* vp) paramsButton->setToggleState(true, true); } - - } - if (owner->isSource()) - backgroundColor = Colour(255, 0, 0);//Colour(int(0.9*255.0f),int(0.019*255.0f),int(0.16*255.0f)); - else if (owner->isSink()) - backgroundColor = Colour(255, 149, 0);//Colour(int(0.06*255.0f),int(0.46*255.0f),int(0.9*255.0f)); - else if (owner->isSplitter() || owner->isMerger()) - backgroundColor = Colour(40, 40, 40);//Colour(int(0.7*255.0f),int(0.7*255.0f),int(0.7*255.0f)); - else - backgroundColor = Colour(255, 89, 0);//Colour(int(1.0*255.0f),int(0.5*255.0f),int(0.0*255.0f)); - - paramsChannels.clear(); audioChannels.clear(); recordChannels.clear(); + backgroundGradient = ColourGradient(Colour(190, 190, 190), 0.0f, 150.0f, + Colour(145, 145, 145), 0.0f, 0.0f, false); + + //grad.addColour(0.5f, Colour(170, 170, 170)); + //grad.addColour(0.5, Colours::lightgrey); + //grad.addColour(1.0f, Colours::grey); + fadeIn(); } @@ -99,6 +97,27 @@ GenericEditor::~GenericEditor() //delete titleFont; } +void GenericEditor::refreshColors() +{ + + enum { + PROCESSOR_COLOR = 801, + FILTER_COLOR = 802, + SINK_COLOR = 803, + SOURCE_COLOR = 804, + UTILITY_COLOR = 805, + }; + + if (getProcessor()->isSource()) + backgroundColor = getProcessorList()->findColour(SOURCE_COLOR);// Colour(255, 0, 0);//Colour(int(0.9*255.0f),int(0.019*255.0f),int(0.16*255.0f)); + else if (getProcessor()->isSink()) + backgroundColor = getProcessorList()->findColour(SINK_COLOR);//Colour(255, 149, 0);//Colour(int(0.06*255.0f),int(0.46*255.0f),int(0.9*255.0f)); + else if (getProcessor()->isSplitter() || getProcessor()->isMerger()) + backgroundColor = getProcessorList()->findColour(UTILITY_COLOR);//Colour(40, 40, 40);//Colour(int(0.7*255.0f),int(0.7*255.0f),int(0.7*255.0f)); + else + backgroundColor = getProcessorList()->findColour(FILTER_COLOR);//Colour(255, 89, 0);//Colour(int(1.0*255.0f),int(0.5*255.0f),int(0.0*255.0f)); + +} void GenericEditor::resized() @@ -211,7 +230,10 @@ void GenericEditor::paint (Graphics& g) g.fillRect(1,1,getWidth()-(2+offset),getHeight()-2); // draw gray workspace - g.setColour(Colour(140, 140, 140)); + //g.setColour(Colour(140, 140, 140)); + + + g.setGradientFill(backgroundGradient); g.fillRect(1,22,getWidth()-2, getHeight()-29); g.setFont(titleFont); @@ -240,7 +262,7 @@ void GenericEditor::paint (Graphics& g) if (isFading) { - g.setColour(Colours::black.withAlpha((float) (15.0-accumulator)/15.0f)); + g.setColour(Colours::black.withAlpha((float) (10.0-accumulator)/10.0f)); if (getWidth() > 0 && getHeight() > 0) g.fillAll(); } @@ -253,7 +275,7 @@ void GenericEditor::timerCallback() repaint(); - if (accumulator > 15.0) + if (accumulator > 10.0) { stopTimer(); isFading = false; @@ -265,6 +287,9 @@ void GenericEditor::buttonClicked(Button* button) checkDrawerButton(button); checkChannelSelectors(button); + + buttonEvent(button); // needed to inform subclasses of + // button event } bool GenericEditor::checkDrawerButton(Button* button) @@ -329,8 +354,18 @@ bool GenericEditor::checkChannelSelectors(Button* button) } else if (recordButton->getToggleState()) { - recordChannels.set(n,button->getToggleState()); - //type = "Record "; + recordChannels.set(n,button->getToggleState()); + int id = getProcessor()->getNodeId(); + + RecordNode* rn = getProcessorGraph()->getRecordNode(); + + std::cout << "Button " << n << " was pressed." << std::endl; + rn->setChannel(id, n); + + if (button->getToggleState()) + rn->setParameter(2, 1.0f); + else + rn->setParameter(2, 0.0f); } else if (paramsButton->getToggleState()) { @@ -410,13 +445,32 @@ bool GenericEditor::checkChannelSelectors(Button* button) } +void GenericEditor::selectChannels(Array<int> arr) +{ + for (int i = 0; i < channelSelectorButtons.size(); i++) + { + channelSelectorButtons[i]->setToggleState(false, false); + } + + for (int i = 0; i < arr.size(); i++) + { + if (i > -1 && i < channelSelectorButtons.size()) + { + channelSelectorButtons[i]->setToggleState(true,false); + } + } + +} + void GenericEditor::update() { - std::cout << "Updating" << std::endl; + std::cout << "Editor for "; GenericProcessor* p = (GenericProcessor*) getProcessor(); + std::cout << p->getName() << " updating settings." << std::endl; + if (!p->isSink()) { @@ -437,6 +491,18 @@ void GenericEditor::update() numChannels = p->getNumInputs(); } + if (numChannels == 0) + { + if (drawerButton != 0) + drawerButton->setVisible(false); + } else { + if (drawerButton != 0) + drawerButton->setVisible(true); + } + + updateVisualizer(); // does nothing unless this method + // has been implemented + } Array<int> GenericEditor::getActiveChannels() @@ -488,12 +554,10 @@ void GenericEditor::createRadioButtons(int x, int y, int w, StringArray values, int GenericEditor::createChannelSelectors() { - GenericProcessor* p = (GenericProcessor*) getProcessor(); - + GenericProcessor* p = getProcessor(); if (channelSelectorButtons.size() == 0) { - int width = 20; int height = 14; int numChannels; @@ -503,7 +567,9 @@ int GenericEditor::createChannelSelectors() else numChannels = p->getNumInputs(); - int nColumns = ceil(numChannels/4); + int nColumns = jmax((int) ceil(numChannels/4),1); + //std::cout << numChannels << " channels" << std::endl; + //std::cout << nColumns << " columns" << std::endl; for (int n = 1; n < numChannels+1; n++) { @@ -725,3 +791,82 @@ void ChannelSelectorButton::paintButton(Graphics &g, bool isMouseOver, bool isBu g.drawText(getName(),0,0,getWidth(),getHeight(),Justification::centred,true); } + +//// BUTTONS //// + +void PlusButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown) +{ + g.fillAll(Colours::orange); + g.setColour(Colours::black); + g.drawRect(0,0,getWidth(),getHeight(),1.0); + + if (isMouseOver) + { + g.setColour(Colours::white); + } else { + g.setColour(Colours::black); + } + + // if (isButtonDown) + // { + // g.setColour(Colours::white); + // } + + int thickness = 1; + int offset = 3; + + g.fillRect(getWidth()/2-thickness, + offset, + thickness*2, + getHeight()-offset*2); + + g.fillRect(offset, + getHeight()/2-thickness, + getWidth()-offset*2, + thickness*2); +} + + +void TriangleButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown) +{ + + // g.fillAll(Colours::orange); + // g.setColour(Colours::black); + // g.drawRect(0,0,getWidth(),getHeight(),1.0); + + if (isMouseOver) + { + g.setColour(Colours::grey); + } else { + g.setColour(Colours::black); + } + + if (isButtonDown) + { + g.setColour(Colours::white); + } + + int inset = 1; + int x1, y1, x2, y2, x3; + + x1 = inset; + x2 = getWidth()/2; + x3 = getWidth()-inset; + + if (direction == 1) + { + y1 = getHeight()-inset; + y2 = inset; + + } else { + y1 = inset; + y2 = getHeight()-inset; + } + + g.drawLine(x1, y1, x2, y2); + g.drawLine(x2, y2, x3, y1); + g.drawLine(x3, y1, x1, y1); + + +} + diff --git a/Source/Processors/Editors/GenericEditor.h b/Source/Processors/Editors/GenericEditor.h index 17f2bac8a09ea1370941add7d06c740244f4a6c1..5530b679b9c55df1e0f0368d63752d0c8179a309 100644 --- a/Source/Processors/Editors/GenericEditor.h +++ b/Source/Processors/Editors/GenericEditor.h @@ -33,7 +33,7 @@ Base class for creating processor editors. - If a processor doesn't have an editor defined, a GenericEditor will be used. + If a processor doesn't havesign an editor defined, a GenericEditor will be used. Classes derived from this class must place their controls as child components. They shouldn't try to re-draw any aspects of their background. @@ -46,19 +46,21 @@ class GenericProcessor; class DrawerButton; class EditorButton; class ChannelSelectorButton; +class TriangleButton; +class PlusButton; class GenericEditor : public AudioProcessorEditor, public Timer, public AccessClass, - public Button::Listener + public Button::Listener, + public Slider::Listener { public: - GenericEditor (GenericProcessor* owner);//, FilterViewport* vp); + GenericEditor (GenericProcessor* owner); virtual ~GenericEditor(); void paint (Graphics& g); - //void setViewport(FilterViewport*); bool keyPressed (const KeyPress& key); @@ -83,7 +85,7 @@ public: virtual void switchSource(int) { } // needed for MergerEditor virtual void switchSource() { }; // needed for MergerEditor - AudioProcessor* getProcessor() const {return getAudioProcessor();} + GenericProcessor* getProcessor() const {return (GenericProcessor*) getAudioProcessor();} void createRadioButtons(int x, int y, int w, StringArray values, const String& name); @@ -96,13 +98,29 @@ public: float accumulator; virtual void buttonClicked(Button* button); + virtual void buttonEvent(Button* button) {} + virtual void sliderValueChanged(Slider* slider) {} bool checkDrawerButton(Button* button); bool checkChannelSelectors(Button* button); + void selectChannels(Array<int>); + + void refreshColors(); + virtual void update(); + virtual void updateVisualizer() {} Array<int> getActiveChannels(); + + Array<bool> audioChannels; + Array<bool> recordChannels; + Array<bool> paramsChannels; + +protected: + DrawerButton* drawerButton; + int drawerWidth; + private: @@ -115,6 +133,7 @@ private: virtual void destroyChannelSelectors(); Colour backgroundColor; + ColourGradient backgroundGradient; bool isSelected; bool isEnabled; @@ -123,27 +142,27 @@ private: int numChannels; - int drawerWidth; - DrawerButton* drawerButton; EditorButton* audioButton; EditorButton* recordButton; EditorButton* paramsButton; - Array<bool> audioChannels; - Array<bool> recordChannels; - Array<bool> paramsChannels; + Array<ChannelSelectorButton*> channelSelectorButtons; ChannelSelectorButton* allButton; ChannelSelectorButton* noneButton; - Font titleFont; String name; +protected: + + Font titleFont; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericEditor); }; @@ -198,5 +217,27 @@ private: Font buttonFont; }; +class TriangleButton : public Button +{ +public: + TriangleButton(int direction_) : Button("Arrow") + {direction = direction_;} + ~TriangleButton() {} +private: + void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown); + + int direction; +}; + +class PlusButton : public Button +{ +public: + PlusButton() : Button("Plus") {} + ~PlusButton() {} +private: + void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown); + +}; + #endif // __GENERICEDITOR_H_DD406E71__ diff --git a/Source/Processors/Editors/LfpDisplayEditor.cpp b/Source/Processors/Editors/LfpDisplayEditor.cpp index afb8b23bea77c4dbae0113c420aab757cfeb5cb5..da81819d1782a1134616553ba3a176034ed9c2b4 100644 --- a/Source/Processors/Editors/LfpDisplayEditor.cpp +++ b/Source/Processors/Editors/LfpDisplayEditor.cpp @@ -21,47 +21,16 @@ */ - #include "LfpDisplayEditor.h" -#include "../Visualization/LfpDisplayCanvas.h" - -SelectorButton::SelectorButton() - : DrawableButton (T("Selector"), DrawableButton::ImageFitted) -{ - DrawablePath normal, over, down; - - Path p; - p.addRectangle (0.0,0.0,20.0,20.0); - normal.setPath (p); - normal.setFill (Colours::lightgrey); - normal.setStrokeThickness (0.0f); - - over.setPath (p); - over.setFill (Colours::black); - over.setStrokeFill (Colours::black); - over.setStrokeThickness (5.0f); - - setImages (&normal, &over, &over); - setBackgroundColours(Colours::darkgrey, Colours::white); - setClickingTogglesState (true); - setTooltip ("Toggle a state."); - -} - -SelectorButton::~SelectorButton() -{ -} LfpDisplayEditor::LfpDisplayEditor (GenericProcessor* parentNode) - : GenericEditor(parentNode), - tabIndex(-1), dataWindow(0), - //streamBuffer(0), eventBuffer(0), canvas(0), - isPlaying(false), - canvas(0) + : VisualizerEditor(parentNode) { + tabText = "LFP"; + desiredWidth = 250; StringArray timeBaseValues; @@ -80,104 +49,25 @@ LfpDisplayEditor::LfpDisplayEditor (GenericProcessor* parentNode) createRadioButtons(35, 90, 160, displayGainValues, "Display Gain"); - // for (int n = 0; n < getNumChildComponents(); n++) - // { - // Button* c = (Button*) getChildComponent(n); - - // if (c->isVisible()) - // c->addListener(this); - - // if (c->getRadioGroupId() != 999) - // c->setVisible(true); - // } - - // timebaseSlider = new Slider (T("Time Base Slider")); - // timebaseSlider->setBounds(60,20,200,40); - // timebaseSlider->setRange(500,10000,500); - // timebaseSlider->addListener(this); - // addAndMakeVisible(timebaseSlider); - - // displayGainSlider = new Slider (T("Display Gain Slider")); - // displayGainSlider->setBounds(60,65,200,40); - // displayGainSlider->setRange(1,8,1); - // displayGainSlider->addListener(this); - // addAndMakeVisible(displayGainSlider); - - // windowSelector = new SelectorButton(); - // windowSelector->addListener(this); - // windowSelector->setBounds(25,25,20,20); - // windowSelector->setToggleState(false,false); - // addAndMakeVisible(windowSelector); - - tabSelector = new SelectorButton(); - tabSelector->addListener(this); - tabSelector->setBounds(205,30,10,10); - - addAndMakeVisible(tabSelector); - tabSelector->setToggleState(false,false); - - //canvas = new LfpDisplayCanvas((LfpDisplayNode*) getProcessor()); - } LfpDisplayEditor::~LfpDisplayEditor() { - - if (tabIndex > -1) - { - getDataViewport()->removeTab(tabIndex); - } - - deleteAllChildren(); - -} - -void LfpDisplayEditor::enable() -{ - std::cout << " Enabling LfpDisplayEditor" << std::endl; - if (canvas != 0) - canvas->beginAnimation(); - - isPlaying = true; -} - -void LfpDisplayEditor::disable() -{ - if (canvas != 0) - canvas->endAnimation(); - - isPlaying = false; } -void LfpDisplayEditor::updateNumInputs(int n) -{ - std::cout << "Setting num inputs on LfpDisplayEditor to " << n << std::endl; - if (canvas != 0) - canvas->updateNumInputs(n); -} -void LfpDisplayEditor::updateSampleRate(float r) +Visualizer* LfpDisplayEditor::createNewCanvas() { - if (canvas != 0) - canvas->updateSampleRate(r); -} -void LfpDisplayEditor::setBuffers(AudioSampleBuffer* asb, MidiBuffer* mb) -{ - std::cout << "LfpDisplayEditor buffers are set!" << std::endl; - //streamBuffer = asb; - //eventBuffer = mb; + LfpDisplayNode* processor = (LfpDisplayNode*) getProcessor(); + return new LfpDisplayCanvas(processor); - //std::cout << streamBuffer << std::endl; - //std::cout << eventBuffer << std::endl; } -void LfpDisplayEditor::buttonClicked(Button* button) +void LfpDisplayEditor::buttonCallback(Button* button) { - if (!checkDrawerButton(button) && !checkChannelSelectors(button)) { - int gId = button->getRadioGroupId(); if (gId > 0) { @@ -186,110 +76,6 @@ void LfpDisplayEditor::buttonClicked(Button* button) canvas->setParameter(gId-1, button->getName().getFloatValue()); } - } else { - - if (canvas == 0) { - - LfpDisplayNode* processor = (LfpDisplayNode*) getProcessor(); - canvas = new LfpDisplayCanvas(processor); - - if (isPlaying) - canvas->beginAnimation(); - } - - // if (button == windowSelector) - // { - // if (dataWindow == 0) { - - // dataWindow = new DataWindow(windowSelector); - - // //if (canvas == 0) - // // canvas = new LfpDisplayCanvas((LfpDisplayNode*) getProcessor()); - - // //dataWindow->setContentComponent(new LfpDisplayCanvas(streamBuffer,eventBuffer,getConfiguration(), this)); - - // if (tabSelector->getToggleState()) - // { - // tabSelector->setToggleState(false, false); - // dataViewport->removeTab(tabIndex); - // tabIndex = -1; - // } - - // //LfpDisplayNode* p = (LfpDisplayNode*) getProcessor(); - - // dataWindow->setContentNonOwned(canvas, false); - // //p->isVisible = true; - - // //getProcessor()->parentComponentChanged(); - // dataWindow->setVisible(true); - - // } else { + } - // if (tabSelector->getToggleState()) - // { - // tabSelector->setToggleState(false, false); - // dataViewport->removeTab(tabIndex); - // tabIndex = -1; - // } - - // dataWindow->setVisible(windowSelector->getToggleState()); - - // //LfpDisplayNode* p = (LfpDisplayNode*) getProcessor(); - // //p->isVisible = windowSelector->getToggleState(); - // //getProcessor()->parentComponentChanged(); - // } - - // } else - if (button == tabSelector) - { - if (tabSelector->getToggleState() && tabIndex < 0) - { - - //std::cout << "Editor data viewport: " << dataViewport << std::endl; - - // if (windowSelector->getToggleState()) - // { - // windowSelector->setToggleState(false, false); - // dataWindow->setVisible(false); - // } - - //tabIndex = dataViewport->addTabToDataViewport("LFP",new LfpDisplayCanvas(streamBuffer,eventBuffer,getConfiguration(), this)); - //Component* p = (Component*) getProcessor(); - - //LfpDisplayNode* p = (LfpDisplayNode*) getProcessor(); - tabIndex = getDataViewport()->addTabToDataViewport("LFP",canvas); - //if (isPlaying) - ///{ - // canvas->beginAnimation(); - //} - - //p->isVisible = true; - - } else if (!tabSelector->getToggleState() && tabIndex > -1) - { - getDataViewport()->removeTab(tabIndex); - tabIndex = -1; - //LfpDisplayNode* p = (LfpDisplayNode*) getProcessor(); - //p->isVisible = false; - } - } - } - } } - -void LfpDisplayEditor::sliderValueChanged (Slider* slider) -{ - - // if (canvas != 0) - // { - // if (slider == timebaseSlider) - // canvas->setParameter(0,slider->getValue()); - // else - // canvas->setParameter(1,slider->getValue()); - // } - - - //else - // getAudioProcessor()->setParameter(1,slider->getValue()); - -} \ No newline at end of file diff --git a/Source/Processors/Editors/LfpDisplayEditor.h b/Source/Processors/Editors/LfpDisplayEditor.h index 255812705be1bb16997cc7e8ab31121cb89ca342..934cf40dc9f802ea9999335c620ca83a28501926 100644 --- a/Source/Processors/Editors/LfpDisplayEditor.h +++ b/Source/Processors/Editors/LfpDisplayEditor.h @@ -31,59 +31,22 @@ #include "../Visualization/DataWindow.h" #include "../LfpDisplayNode.h" #include "../Visualization/LfpDisplayCanvas.h" +#include "VisualizerEditor.h" -//class FilterViewport; -//class DataViewport; -class DataWindow; -class LfpDisplayCanvas; +class Visualizer; -class SelectorButton : public DrawableButton -{ - public: - SelectorButton(); - ~SelectorButton(); -}; - -class LfpDisplayEditor : public GenericEditor,//, - // public Button::Listener, - public Slider::Listener +class LfpDisplayEditor : public VisualizerEditor { public: LfpDisplayEditor (GenericProcessor*); ~LfpDisplayEditor(); - void buttonClicked (Button* button); - void setBuffers (AudioSampleBuffer*, MidiBuffer*); - //void setUIComponent (UIComponent* ui) {UI = ui;} - - void sliderValueChanged (Slider* slider); - - void enable(); - void disable(); + void buttonCallback (Button* button); - void updateNumInputs(int); - void updateSampleRate(float); + Visualizer* createNewCanvas(); private: - bool isPlaying; - - ScopedPointer <DataWindow> dataWindow; - - Slider* timebaseSlider; - Slider* displayGainSlider; - - SelectorButton* windowSelector; - SelectorButton* tabSelector; - - ScopedPointer <LfpDisplayCanvas> canvas; - - //AudioSampleBuffer* streamBuffer; - //MidiBuffer* eventBuffer; - //UIComponent* UI; - //DataViewport* dataViewport; - - int tabIndex; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LfpDisplayEditor); diff --git a/Source/Processors/Editors/MergerEditor.cpp b/Source/Processors/Editors/MergerEditor.cpp index 1fa5234af7b1298f8920ab5ee46171c962eacc3a..5c21d4104142a73a9694c153847b98aaf55023ae 100644 --- a/Source/Processors/Editors/MergerEditor.cpp +++ b/Source/Processors/Editors/MergerEditor.cpp @@ -94,21 +94,21 @@ MergerEditor::~MergerEditor() deleteAllChildren(); } -void MergerEditor::buttonClicked(Button* button) +void MergerEditor::buttonEvent(Button* button) { if (button == pipelineSelectorA) { pipelineSelectorA->setToggleState(true,false); pipelineSelectorB->setToggleState(false,false); Merger* processor = (Merger*) getProcessor(); - processor->switchSource(0); + processor->switchIO(0); } else if (button == pipelineSelectorB) { pipelineSelectorB->setToggleState(true,false); pipelineSelectorA->setToggleState(false,false); Merger* processor = (Merger*) getProcessor(); - processor->switchSource(1); + processor->switchIO(1); } } @@ -120,14 +120,14 @@ void MergerEditor::switchSource(int source) pipelineSelectorA->setToggleState(true,false); pipelineSelectorB->setToggleState(false,false); Merger* processor = (Merger*) getProcessor(); - processor->switchSource(0); + processor->switchIO(0); } else if (source == 1) { pipelineSelectorB->setToggleState(true,false); pipelineSelectorA->setToggleState(false,false); Merger* processor = (Merger*) getProcessor(); - processor->switchSource(1); + processor->switchIO(1); } } @@ -143,6 +143,6 @@ void MergerEditor::switchSource() pipelineSelectorA->setToggleState(!isAOn,false); Merger* processor = (Merger*) getProcessor(); - processor->switchSource(); + processor->switchIO(); } \ No newline at end of file diff --git a/Source/Processors/Editors/MergerEditor.h b/Source/Processors/Editors/MergerEditor.h index 51f9b2b1b78fced1c6275587f80c1ad6fe34598f..889e070f4989ad31488b6b5a085451566b342561 100644 --- a/Source/Processors/Editors/MergerEditor.h +++ b/Source/Processors/Editors/MergerEditor.h @@ -42,7 +42,7 @@ public: MergerEditor (GenericProcessor* parentNode); virtual ~MergerEditor(); - virtual void buttonClicked (Button* button); + virtual void buttonEvent (Button* button); void switchSource(int); void switchSource (); diff --git a/Source/Processors/Editors/SignalGeneratorEditor.cpp b/Source/Processors/Editors/SignalGeneratorEditor.cpp index ccf5a351e49bbb4524d20167d34158552d025a28..faddc33b5b54a6c20793542cac897d0b5e4f9311 100644 --- a/Source/Processors/Editors/SignalGeneratorEditor.cpp +++ b/Source/Processors/Editors/SignalGeneratorEditor.cpp @@ -24,27 +24,68 @@ #include "SignalGeneratorEditor.h" #include "../SignalGenerator.h" +#include "../../UI/EditorViewport.h" #include <stdio.h> SignalGeneratorEditor::SignalGeneratorEditor (GenericProcessor* parentNode) - : GenericEditor(parentNode), amplitudeSlider(0), frequencySlider(0) + : GenericEditor(parentNode), amplitudeSlider(0), frequencySlider(0), phaseSlider(0) { - desiredWidth = 250; + desiredWidth = 270; + + int buttonWidth = 31; + int buttonHeight = 19; + + for (int i = 0; i < 5; i++) + { + WaveformSelector* ws = new WaveformSelector(i); + ws->setBounds(15 + (buttonWidth)*i, 30, buttonWidth, buttonHeight); + ws->addListener(this); + waveformSelectors.add(ws); + addAndMakeVisible(ws); + } - amplitudeSlider = new Slider (T("Amplitude Slider")); - amplitudeSlider->setBounds(25,40,170,40); - amplitudeSlider->setRange(0.005,0.05,0.005); + amplitudeSlider = new Slider ("Amplitude Slider"); + amplitudeSlider->setBounds(10,60,50,60); + amplitudeSlider->setRange(0,1000,10); amplitudeSlider->addListener(this); + amplitudeSlider->setSliderStyle(Slider::Rotary); + amplitudeSlider->setTextBoxStyle(Slider::TextBoxBelow, false, 40, 20); addAndMakeVisible(amplitudeSlider); - frequencySlider = new Slider (T("High-Cut Slider")); - frequencySlider->setBounds(25,70,170,40); + frequencySlider = new Slider ("Frequency Slider"); + frequencySlider->setBounds(70,60,50,60); frequencySlider->setRange(1,1000,1); frequencySlider->addListener(this); + frequencySlider->setSliderStyle(Slider::Rotary); + frequencySlider->setTextBoxStyle(Slider::TextBoxBelow, false, 40, 20); addAndMakeVisible(frequencySlider); + phaseSlider = new Slider ("Phase Slider"); + phaseSlider->setBounds(130,60,50,60); + phaseSlider->setRange(0, 360, 1); + phaseSlider->addListener(this); + phaseSlider->setSliderStyle(Slider::Rotary); + phaseSlider->setTextBoxStyle(Slider::TextBoxBelow, false, 40, 20); + addAndMakeVisible(phaseSlider); + + numChannelsLabel = new Label("Number of Channels","1"); + numChannelsLabel->setEditable(true); + numChannelsLabel->addListener(this); + numChannelsLabel->setBounds(200,50,25,20); + addAndMakeVisible(numChannelsLabel); + + upButton = new TriangleButton(1); + upButton->addListener(this); + upButton->setBounds(200,30,20,15); + addAndMakeVisible(upButton); + + downButton = new TriangleButton(2); + downButton->addListener(this); + downButton->setBounds(200,75,20,15); + addAndMakeVisible(downButton); + } SignalGeneratorEditor::~SignalGeneratorEditor() @@ -67,10 +108,144 @@ void SignalGeneratorEditor::sliderValueChanged (Slider* slider) if (slider == amplitudeSlider) p->setParameter(0,slider->getValue()); - else + else if (slider == frequencySlider) p->setParameter(1,slider->getValue()); + else if (slider == phaseSlider) + p->setParameter(2,slider->getValue()); + + } + + +} + +void SignalGeneratorEditor::buttonEvent (Button* button) +{ + + for (int i = 0; i < waveformSelectors.size(); i++) + { + if (button == waveformSelectors[i]) + { + + Array<int> chans = getActiveChannels(); + + GenericProcessor* p = getProcessor(); + + for (int n = 0; n < chans.size(); n++) { + + p->setCurrentChannel(chans[n]); + p->setParameter(3,(float) i); + + } + + } } + int num = numChannelsLabel->getText().getIntValue(); + if (button == upButton) + { + numChannelsLabel->setText(String(++num), true); + + } else if (button == downButton) + { + + if (num > 1) + numChannelsLabel->setText(String(--num), true); + + } +} + + +void SignalGeneratorEditor::labelTextChanged (Label* label) +{ + + SignalGenerator* sg = (SignalGenerator*) getProcessor(); + sg->nOut = numChannelsLabel->getText().getIntValue(); + getEditorViewport()->makeEditorVisible(this); +} + +WaveformSelector::WaveformSelector(int type) : Button("Waveform") +{ + + setRadioGroupId(299); + setClickingTogglesState(true); + + if (type == 0) { + selected = ImageCache::getFromMemory (BinaryData::RadioButtons_selected01_png, + BinaryData::RadioButtons_selected01_pngSize); + selectedOver= ImageCache::getFromMemory (BinaryData::RadioButtons_selected_over01_png, + BinaryData::RadioButtons_selected_over01_pngSize); + neutral = ImageCache::getFromMemory (BinaryData::RadioButtons_neutral01_png, + BinaryData::RadioButtons_neutral01_pngSize); + neutralOver = ImageCache::getFromMemory (BinaryData::RadioButtons01_png, + BinaryData::RadioButtons01_pngSize); + } + else if (type == 1) { + selected = ImageCache::getFromMemory (BinaryData::RadioButtons_selected02_png, + BinaryData::RadioButtons_selected02_pngSize); + selectedOver= ImageCache::getFromMemory (BinaryData::RadioButtons_selected_over02_png, + BinaryData::RadioButtons_selected_over02_pngSize); + neutral = ImageCache::getFromMemory (BinaryData::RadioButtons_neutral02_png, + BinaryData::RadioButtons_neutral02_pngSize); + neutralOver = ImageCache::getFromMemory (BinaryData::RadioButtons02_png, + BinaryData::RadioButtons02_pngSize); + } + else if (type == 2) { + selected = ImageCache::getFromMemory (BinaryData::RadioButtons_selected03_png, + BinaryData::RadioButtons_selected03_pngSize); + selectedOver= ImageCache::getFromMemory (BinaryData::RadioButtons_selected_over03_png, + BinaryData::RadioButtons_selected_over03_pngSize); + neutral = ImageCache::getFromMemory (BinaryData::RadioButtons_neutral03_png, + BinaryData::RadioButtons_neutral03_pngSize); + neutralOver = ImageCache::getFromMemory (BinaryData::RadioButtons03_png, + BinaryData::RadioButtons03_pngSize); + } + else if (type == 3) { + selected = ImageCache::getFromMemory (BinaryData::RadioButtons_selected04_png, + BinaryData::RadioButtons_selected04_pngSize); + selectedOver= ImageCache::getFromMemory (BinaryData::RadioButtons_selected_over04_png, + BinaryData::RadioButtons_selected_over04_pngSize); + neutral = ImageCache::getFromMemory (BinaryData::RadioButtons_neutral04_png, + BinaryData::RadioButtons_neutral04_pngSize); + neutralOver = ImageCache::getFromMemory (BinaryData::RadioButtons04_png, + BinaryData::RadioButtons04_pngSize); + } + else if (type == 4) { + selected = ImageCache::getFromMemory (BinaryData::RadioButtons_selected05_png, + BinaryData::RadioButtons_selected05_pngSize); + selectedOver= ImageCache::getFromMemory (BinaryData::RadioButtons_selected_over05_png, + BinaryData::RadioButtons_selected_over05_pngSize); + neutral = ImageCache::getFromMemory (BinaryData::RadioButtons_neutral05_png, + BinaryData::RadioButtons_neutral05_pngSize); + neutralOver = ImageCache::getFromMemory (BinaryData::RadioButtons05_png, + BinaryData::RadioButtons05_pngSize); + } + +} + +void WaveformSelector::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown) +{ + + + if (getToggleState()) + { + if (isMouseOver) + g.drawImage(selectedOver, 0, 0, 31, 19, 0, 0, 31, 19); + else + g.drawImage(selected, 0, 0, 31, 19, 0, 0, 31, 19); + } else { + if (isMouseOver) + g.drawImage(neutralOver, 0, 0, 31, 19, 0, 0, 31, 19); + else + g.drawImage(neutral, 0, 0, 31, 19, 0, 0, 31, 19); + } + + // g.fillAll(); + + // g.setColour(Colours::black); + // g.drawRect(0, 0, getWidth(), getHeight()); + + // g.setImageResamplingQuality(Graphics::highResamplingQuality); + } \ No newline at end of file diff --git a/Source/Processors/Editors/SignalGeneratorEditor.h b/Source/Processors/Editors/SignalGeneratorEditor.h index 00aae333669d0607b13662a6e24c8313ad7a42b9..ffe55aa6cc87fd4dace829a8d53f8c2f78b498e6 100644 --- a/Source/Processors/Editors/SignalGeneratorEditor.h +++ b/Source/Processors/Editors/SignalGeneratorEditor.h @@ -28,22 +28,55 @@ #include "GenericEditor.h" class FilterViewport; +class WaveformSelector; class SignalGeneratorEditor : public GenericEditor, - public Slider::Listener + public Label::Listener { public: SignalGeneratorEditor (GenericProcessor* parentNode); virtual ~SignalGeneratorEditor(); void sliderValueChanged (Slider* slider); + void buttonEvent(Button* button); + void labelTextChanged(Label* label); private: + + Label* numChannelsLabel; + TriangleButton* upButton; + TriangleButton* downButton; + Slider* amplitudeSlider; Slider* frequencySlider; + Slider* phaseSlider; + + Array<WaveformSelector*> waveformSelectors; + + enum wvfrm + { + SINE, SQUARE, SAW, TRIANGLE, NOISE + }; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SignalGeneratorEditor); }; +class WaveformSelector : public Button +{ +public: + WaveformSelector(int type_); + ~WaveformSelector() {} +private: + void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown); + + int type; + + Image neutral; + Image neutralOver; + Image selected; + Image selectedOver; + +}; + #endif // __SIGNALGENERATOREDITOR_H_841A7078__ diff --git a/Source/Processors/Editors/SpikeDetectorEditor.cpp b/Source/Processors/Editors/SpikeDetectorEditor.cpp index bb395088e26e85ae98463b172625b0119266039d..c3e480bea000a976a70f01d7dea63ded216ca36d 100644 --- a/Source/Processors/Editors/SpikeDetectorEditor.cpp +++ b/Source/Processors/Editors/SpikeDetectorEditor.cpp @@ -27,30 +27,320 @@ SpikeDetectorEditor::SpikeDetectorEditor (GenericProcessor* parentNode) - : GenericEditor(parentNode), threshSlider(0) + : GenericEditor(parentNode), isPlural(true) { - desiredWidth = 200; - threshSlider = new Slider (T("Threshold Slider")); - threshSlider->setBounds(25,20,150,40); - threshSlider->setRange(1000,20000,1000); - threshSlider->addListener(this); - addAndMakeVisible(threshSlider); + MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false); + Typeface::Ptr typeface = new CustomTypeface(mis); + font = Font(typeface); + + desiredWidth = 370; + + electrodeTypes = new ComboBox("Electrode Types"); + + SpikeDetector* processor = (SpikeDetector*) getProcessor(); + + for (int i = 0; i < processor->electrodeTypes.size(); i++) + { + String type = processor->electrodeTypes[i]; + electrodeTypes->addItem (type += "s", i+1); + } + + electrodeTypes->setEditableText(false); + electrodeTypes->setJustificationType (Justification::centredLeft); + electrodeTypes->addListener(this); + electrodeTypes->setBounds(65,40,130,16); + electrodeTypes->setSelectedId(4); + addAndMakeVisible(electrodeTypes); + + electrodeList = new ComboBox("Electrode List"); + electrodeList->setEditableText(false); + electrodeList->setJustificationType (Justification::centredLeft); + electrodeList->addListener(this); + electrodeList->setBounds(20,80,115,20); + addAndMakeVisible(electrodeList); + + numElectrodes = new Label("Number of Electrodes","4"); + numElectrodes->setEditable(true); + numElectrodes->addListener(this); + numElectrodes->setBounds(30,40,25,20); + //labelTextChanged(numElectrodes); + addAndMakeVisible(numElectrodes); + + upButton = new TriangleButton(1); + upButton->addListener(this); + upButton->setBounds(50,40,10,8); + addAndMakeVisible(upButton); + + downButton = new TriangleButton(2); + downButton->addListener(this); + downButton->setBounds(50,50,10,8); + addAndMakeVisible(downButton); + + plusButton = new PlusButton(); + plusButton->addListener(this); + plusButton->setBounds(15,42,14,14); + addAndMakeVisible(plusButton); + + ElectrodeEditorButton* e1 = new ElectrodeEditorButton("EDIT",font); + e1->addListener(this); + addAndMakeVisible(e1); + e1->setBounds(250,80,70,10); + electrodeEditorButtons.add(e1); + + ElectrodeEditorButton* e2 = new ElectrodeEditorButton("MONITOR",font); + e2->addListener(this); + addAndMakeVisible(e2); + e2->setBounds(250,95,70,10); + electrodeEditorButtons.add(e2); + + ElectrodeEditorButton* e3 = new ElectrodeEditorButton("DELETE",font); + e3->addListener(this); + addAndMakeVisible(e3); + e3->setBounds(250,110,70,10); + electrodeEditorButtons.add(e3); + } SpikeDetectorEditor::~SpikeDetectorEditor() { + for (int i = 0; i < electrodeButtons.size(); i++) + { + removeChildComponent(electrodeButtons[i]); + } + deleteAllChildren(); } -void SpikeDetectorEditor::sliderValueChanged (Slider* slider) +void SpikeDetectorEditor::buttonEvent(Button* button) +{ + + int num = numElectrodes->getText().getIntValue(); + + if (button == upButton) + { + numElectrodes->setText(String(++num), true); + + } else if (button == downButton) + { + + if (num > 1) + numElectrodes->setText(String(--num), true); + + } else if (button == plusButton) + { + // std::cout << "Plus button pressed!" << std::endl; + + for (int n = 0; n < num; n++) + { + addElectrode(electrodeTypes->getSelectedId()); + } + + refreshElectrodeList(); + + electrodeList->setSelectedId(electrodeList->getNumItems(), true); + electrodeList->setText(electrodeList->getItemText(electrodeList->getNumItems()-1)); + lastId = electrodeList->getNumItems(); + electrodeList->setEditableText(true); + + drawElectrodeButtons(electrodeList->getNumItems()-1); + + } else if (button == electrodeEditorButtons[0]) // EDIT + { + + for (int i = 0; i < electrodeButtons.size(); i++) + { + if (button->getToggleState()) + { + electrodeButtons[i]->setToggleState(false, false); + electrodeButtons[i]->setRadioGroupId(299); + } else { + electrodeButtons[i]->setToggleState(true, false); + electrodeButtons[i]->setRadioGroupId(0); + } + } + + + } else if (button == electrodeEditorButtons[1]) // MONITOR + { + + } else if (button == electrodeEditorButtons[2]) // DELETE + { + + removeElectrode(electrodeList->getSelectedItemIndex()); + } +} + +void SpikeDetectorEditor::refreshElectrodeList() { + electrodeList->clear(); + + SpikeDetector* processor = (SpikeDetector*) getProcessor(); + + StringArray electrodeNames = processor->getElectrodeNames(); + + for (int i = 0; i < electrodeNames.size(); i++) + { + electrodeList->addItem (electrodeNames[i], electrodeList->getNumItems()+1); + } +} + +void SpikeDetectorEditor::addElectrode(int nChans) +{ + SpikeDetector* processor = (SpikeDetector*) getProcessor(); + processor->addElectrode(nChans); +} + + +void SpikeDetectorEditor::removeElectrode(int index) +{ + std::cout << "Deleting electrode number " << index << std::endl; + SpikeDetector* processor = (SpikeDetector*) getProcessor(); + processor->removeElectrode(index); + refreshElectrodeList(); + + int newIndex = jmin(index, electrodeList->getNumItems()-1); + newIndex = jmax(newIndex, 0); + + electrodeList->setSelectedId(newIndex, true); + electrodeList->setText(electrodeList->getItemText(newIndex)); + + if (electrodeList->getNumItems() == 0) + { + electrodeButtons.clear(); + electrodeList->setEditableText(false); + } +} - if (slider == threshSlider) - getAudioProcessor()->setParameter(0,slider->getValue()); +void SpikeDetectorEditor::labelTextChanged(Label* label) +{ + if (label->getText().equalsIgnoreCase("1") && isPlural) + { + for (int n = 1; n < 21; n++) + { + electrodeTypes->changeItemText(n, + electrodeTypes->getItemText(n-1).trimCharactersAtEnd("s")); + } + + isPlural = false; + + String currentText = electrodeTypes->getText(); + electrodeTypes->setText(currentText.trimCharactersAtEnd("s")); + + } else if (!label->getText().equalsIgnoreCase("1") && !isPlural) + { + const String s = "s"; + size_t one = 1; + + for (int n = 1; n < 21; n++) + { + String currentString = electrodeTypes->getItemText(n-1); + currentString += "s"; + + electrodeTypes->changeItemText(n,currentString); + } + isPlural = true; + + String currentText = electrodeTypes->getText(); + electrodeTypes->setText(currentText += "s"); + } + +} + +void SpikeDetectorEditor::comboBoxChanged(ComboBox* comboBox) +{ + + if (comboBox == electrodeList) + { + int ID = comboBox->getSelectedId(); + + if (ID == 0) + { + SpikeDetector* processor = (SpikeDetector*) getProcessor(); + + processor->setName(lastId, comboBox->getText()); + refreshElectrodeList(); + + } else { + + lastId = ID; + + drawElectrodeButtons(ID-1); + + } + + } +} + +void SpikeDetectorEditor::drawElectrodeButtons(int ID) +{ + + SpikeDetector* processor = (SpikeDetector*) getProcessor(); + + electrodeButtons.clear(); + + int width = 20; + int height = 15; + + int numChannels = processor->getNumChannels(ID); + int row = 0; + int column = 0; + + for (int i = 0; i < numChannels; i++) + { + ElectrodeButton* button = new ElectrodeButton(processor->getChannel(ID,i)); + electrodeButtons.add(button); + + button->setBounds(150+(column++)*width, 80+row*height, width, 15); + addAndMakeVisible(button); + + if (column%5 == 0) + { + column = 0; + row++; + } + + } + +} + + + + +void ElectrodeButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown) +{ + if (getToggleState() == true) + g.setColour(Colours::orange); + else + g.setColour(Colours::darkgrey); + + if (isMouseOver) + g.setColour(Colours::white); + + g.fillRect(0,0,getWidth(),getHeight()); + + // g.setFont(buttonFont); + g.setColour(Colours::black); + + g.drawRect(0,0,getWidth(),getHeight(),1.0); + + g.drawText(String(chan),0,0,getWidth(),getHeight(),Justification::centred,true); +} + + +void ElectrodeEditorButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown) +{ + if (getToggleState() == true) + g.setColour(Colours::darkgrey); + else + g.setColour(Colours::lightgrey); + + g.setFont(font); + + g.drawText(name,0,0,getWidth(),getHeight(),Justification::left,true); +} -} \ No newline at end of file diff --git a/Source/Processors/Editors/SpikeDetectorEditor.h b/Source/Processors/Editors/SpikeDetectorEditor.h index c181e801f17a1eea7461b078ab12b6baf4d3a5a6..0fc9544400ec4745a5c50fc5530670d17b1adea8 100644 --- a/Source/Processors/Editors/SpikeDetectorEditor.h +++ b/Source/Processors/Editors/SpikeDetectorEditor.h @@ -28,21 +28,83 @@ #include "../../../JuceLibraryCode/JuceHeader.h" #include "GenericEditor.h" -class FilterViewport; +class TriangleButton; +class PlusButton; + +class ElectrodeButton : public Button +{ +public: + ElectrodeButton(int chan_) : Button("Electrode"), chan(chan_) + { + setClickingTogglesState(true); + //setRadioGroupId(299); + setToggleState(true, false); + } + ~ElectrodeButton() {} +private: + void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown); + + int chan; +}; + +class ElectrodeEditorButton : public Button +{ +public: + ElectrodeEditorButton(const String& name_, Font font_) : Button("Electrode Editor"), + name(name_), font(font_) + { + if (name.equalsIgnoreCase("edit") || name.equalsIgnoreCase("monitor")) + setClickingTogglesState(true); + } + ~ElectrodeEditorButton() {} +private: + void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown); + + const String name; + + Font font; + +}; + class SpikeDetectorEditor : public GenericEditor, - public Slider::Listener + public Label::Listener, + public ComboBox::Listener + { public: SpikeDetectorEditor (GenericProcessor* parentNode); virtual ~SpikeDetectorEditor(); - void sliderValueChanged (Slider* slider); + void buttonEvent(Button* button); + void labelTextChanged(Label* label); + void comboBoxChanged(ComboBox* comboBox); private: - Slider* threshSlider; - DocumentWindow* docWindow; - //int tabIndex; + void drawElectrodeButtons(int); + + void refreshElectrodeList(); + + ComboBox* electrodeTypes; + ComboBox* electrodeList; + Label* numElectrodes; + TriangleButton* upButton; + TriangleButton* downButton; + PlusButton* plusButton; + + OwnedArray<ElectrodeButton> electrodeButtons; + Array<ElectrodeEditorButton*> electrodeEditorButtons; + + void addElectrode(int nChans); + void removeElectrode(int index); + void editElectrode(int index, int chan, int newChan); + + int lastId; + bool isPlural; + + Font font; + + //ThresholdSlider* thresholdSlider; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDetectorEditor); diff --git a/Source/Processors/Editors/SpikeDisplayEditor.cpp b/Source/Processors/Editors/SpikeDisplayEditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5118577e4fefbf43471d1458cf2682ab442c7f0e --- /dev/null +++ b/Source/Processors/Editors/SpikeDisplayEditor.cpp @@ -0,0 +1,223 @@ +#include "SpikeDisplayEditor.h" +#include <string> + + + +SpikeDisplayEditor::SpikeDisplayEditor (GenericProcessor* parentNode) + : VisualizerEditor(parentNode,200) + +{ + // Get the number of sub channels from the parentNode + // Assume all plots have the same number of subChannels + // Otherwise we'll have to track the number of subChannels + nSubChannels = 4; + + for (int i=0; i<nSubChannels; i++) + subChanSelected[i] = true; + + initializeButtons(); + + tabText = "Spikes"; + +} + +SpikeDisplayEditor::~SpikeDisplayEditor() +{ + deleteAllChildren(); +} + +void SpikeDisplayEditor::initializeButtons(){ + int w = 18; + int h = 18; + int xPad = 5; + int yPad = 6; + + int xInitial = 10; + int yInitial = 25; + int x = xInitial; + int y = yInitial; + + panLabel = new Label("PanLabel", "Pan:"); + panLabel->setBounds(x-xPad, y, w*2 + xPad, h); + panLabel->setJustificationType(Justification::centredLeft ); + x+= 2*w+3*xPad; + + zoomLabel = new Label("ZoomLabel", "Zoom:"); + zoomLabel->setBounds(x-xPad,y,w*3+xPad, h); + zoomLabel->setJustificationType(Justification::centredLeft); + x = xInitial; + y += h + yPad/2; + + panUpBtn = new ChannelSelectorButton("+", titleFont); + panUpBtn->setBounds(x, y, w, h); + panUpBtn->setClickingTogglesState(false); + panUpBtn->addListener(this); + x+= w+xPad; + + panDownBtn = new ChannelSelectorButton("-", titleFont); + panDownBtn->setBounds(x, y, w, h); + panDownBtn->setClickingTogglesState(false); + panDownBtn->addListener(this); + x+= w+xPad*2; + + zoomInBtn = new ChannelSelectorButton("+", titleFont); + zoomInBtn->setBounds(x,y,w,h); + zoomInBtn->setClickingTogglesState(false); + zoomInBtn->addListener(this); + x += w + xPad; + + zoomOutBtn = new ChannelSelectorButton("-", titleFont); + zoomOutBtn->setBounds(x,y,w,h); + zoomOutBtn->setClickingTogglesState(false); + zoomOutBtn->addListener(this); + x += w + xPad*3; + + + clearBtn = new ChannelSelectorButton("Clear", titleFont); + clearBtn->setBounds(x, y, w*2 + xPad, h); + clearBtn->setClickingTogglesState(false); + clearBtn->addListener(this); + x += (w + xPad) *2; + + + +/* + x = xInitial; + y += h + yPad; + + //panLabel->setFont(titleFont); + + saveImgBtn = new ChannelSelectorButton("Save", titleFont); + saveImgBtn->setBounds(x,y,w*2 + xPad, h); + saveImgBtn->setClickingTogglesState(false); + saveImgBtn->addListener(this); + x += (w + xPad) * 2; + + */ + + + + //zoomLabel->setFont(titleFont); + x = xInitial; + y += h + yPad; + // Button *zoomOutBtn = new EditorButton("-"); + + subChanLabel = new Label("SubChan", "Sub Channel:"); + subChanLabel->setBounds(x - xPad,y,w*8, h); + subChanLabel->setJustificationType(Justification::centredLeft); + y += h + yPad/2; + //x += w/2; + + allSubChansBtn = new ChannelSelectorButton("All", titleFont); + allSubChansBtn->setBounds(x,y,w*2+xPad,h); + allSubChansBtn->addListener(this); + allSubChansBtn->setToggleState(true, false); + x += (w+xPad) * 2; + + for (int i=0; i<nSubChannels; i++) + { + String s = ""; + s += i; + + subChanBtn[i] = new ChannelSelectorButton(s, titleFont); + subChanBtn[i]->setBounds(x,y,w,h); + subChanBtn[i]->addListener(this); + subChanBtn[i]->setToggleState(true, false); + x += w + xPad; + } + + + + addAndMakeVisible(panUpBtn); + addAndMakeVisible(panDownBtn); + addAndMakeVisible(panLabel); + + + addAndMakeVisible(zoomInBtn); + addAndMakeVisible(zoomOutBtn); + addAndMakeVisible(zoomLabel); + addAndMakeVisible(clearBtn); + //addAndMakeVisible(saveImgBtn); + + addAndMakeVisible(subChanLabel); + addAndMakeVisible(allSubChansBtn); + for (int i=0; i<nSubChannels; i++) + addAndMakeVisible(subChanBtn[i]); + +} + +Visualizer* SpikeDisplayEditor::createNewCanvas() +{ + + SpikeDisplayNode* processor = (SpikeDisplayNode*) getProcessor(); + return new SpikeDisplayCanvas(processor); + +} + +void SpikeDisplayEditor::buttonCallback(Button* button) +{ + //std::cout<<"Got event from component:"<<button<<std::endl; + + int pIdx = 0; + if (button == panUpBtn){ + for (int i=0; i<nSubChannels; i++) + if (subChanSelected[i]) + canvas->setParameter(SPIKE_CMD_PAN_AXES, pIdx, i, 1); + } + else if (button == panDownBtn){ + for (int i=0; i<nSubChannels; i++) + if (subChanSelected[i]) + canvas->setParameter(SPIKE_CMD_PAN_AXES, pIdx, i, -1); + } + else if (button == zoomInBtn){ + for (int i=0; i<nSubChannels; i++) + if (subChanSelected[i]) + canvas->setParameter(SPIKE_CMD_ZOOM_AXES, pIdx, i, -1); + } + else if (button == zoomOutBtn) + { + for (int i=0; i<nSubChannels; i++) + if (subChanSelected[i]) + canvas->setParameter(SPIKE_CMD_ZOOM_AXES, pIdx, i, 1); + } + + else if (button == clearBtn){ + std::cout<<"Clear!"<<std::endl; + canvas->setParameter(SPIKE_CMD_CLEAR_ALL, 0); + } + else if (button == saveImgBtn) + std::cout<<"Save!"<<std::endl; + + // toggle all sub channel buttons + else if (button == allSubChansBtn) + { + bool b = allSubChansBtn->getToggleState(); + for (int i=0; i<nSubChannels; i++) + subChanBtn[i]->setToggleState(b, true); + + } + // Check the sub Channel selection buttons one by one + else{ + // If the user has clicked a sub channel button then the all channels button should be untoggled if toggled + allSubChansBtn->setToggleState(false, false); + for (int i=0; i<nSubChannels; i++) + if(button == subChanBtn[i]) + { + std::cout<<"SubChannel:"<<i<< " set to:"; + subChanSelected[i] = ((ChannelSelectorButton*) button)->getToggleState(); + std::cout<< subChanSelected[i]<<std::endl; + } + + // If the user has toggled all of the sub channels on, then set AllChans to on + bool allChansToggled = true; + for (int i=0; i<nSubChannels; i++) + { + if (subChanBtn[i]->getToggleState()!=allChansToggled){ + allChansToggled = false; + break; + } + } + allSubChansBtn->setToggleState(allChansToggled, false); + + } +} diff --git a/Source/Processors/Editors/SpikeDisplayEditor.h b/Source/Processors/Editors/SpikeDisplayEditor.h new file mode 100644 index 0000000000000000000000000000000000000000..e5d4fd393d0176ed78a8408b5ff42f5bfd3fb765 --- /dev/null +++ b/Source/Processors/Editors/SpikeDisplayEditor.h @@ -0,0 +1,74 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef SPIKEDISPLAYEDITOR_H_ +#define SPIKEDISPLAYEDITOR_H_ + +#include "../../../JuceLibraryCode/JuceHeader.h" +#include "GenericEditor.h" +#include "../../UI/UIComponent.h" +#include "../../UI/DataViewport.h" +#include "../Visualization/DataWindow.h" +#include "../SpikeDisplayNode.h" +#include "../Visualization/SpikeDisplayCanvas.h" +#include "VisualizerEditor.h" + +#define MAX_N_SUB_CHAN 8 +class Visualizer; + +class SpikeDisplayEditor : public VisualizerEditor +{ +public: + SpikeDisplayEditor (GenericProcessor*); + ~SpikeDisplayEditor(); + + void buttonCallback (Button* button); + + Visualizer* createNewCanvas(); + +private: + + Button *panUpBtn; + Button *panDownBtn; + Button *zoomInBtn; + Button *zoomOutBtn; + Button *clearBtn; + Button *saveImgBtn; + + Label *panLabel; + Label *zoomLabel; + + Button *allSubChansBtn; + + int nSubChannels; + Label *subChanLabel; + Button *subChanBtn[MAX_N_SUB_CHAN]; + bool subChanSelected[MAX_N_SUB_CHAN]; + + void initializeButtons(); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayEditor); + +}; + +#endif // SPIKEDISPLAYEDITOR_H_ diff --git a/Source/Processors/Editors/SplitterEditor.cpp b/Source/Processors/Editors/SplitterEditor.cpp index 20de8670ce3d5c47f4b5683ed0171deff233e8db..e70a8340d8dacb3aa3bbbfe9d70fdd095fc0ab5e 100644 --- a/Source/Processors/Editors/SplitterEditor.cpp +++ b/Source/Processors/Editors/SplitterEditor.cpp @@ -94,21 +94,21 @@ SplitterEditor::~SplitterEditor() deleteAllChildren(); } -void SplitterEditor::buttonClicked(Button* button) +void SplitterEditor::buttonEvent(Button* button) { if (button == pipelineSelectorA) { pipelineSelectorA->setToggleState(true,false); pipelineSelectorB->setToggleState(false,false); Splitter* processor = (Splitter*) getProcessor(); - processor->switchDest(0); + processor->switchIO(0); } else if (button == pipelineSelectorB) { pipelineSelectorB->setToggleState(true,false); pipelineSelectorA->setToggleState(false,false); Splitter* processor = (Splitter*) getProcessor(); - processor->switchDest(1); + processor->switchIO(1); } } @@ -120,14 +120,14 @@ void SplitterEditor::switchDest(int dest) pipelineSelectorA->setToggleState(true,false); pipelineSelectorB->setToggleState(false,false); Splitter* processor = (Splitter*) getProcessor(); - processor->switchDest(0); + processor->switchIO(0); } else if (dest == 1) { pipelineSelectorB->setToggleState(true,false); pipelineSelectorA->setToggleState(false,false); Splitter* processor = (Splitter*) getProcessor(); - processor->switchDest(1); + processor->switchIO(1); } } \ No newline at end of file diff --git a/Source/Processors/Editors/SplitterEditor.h b/Source/Processors/Editors/SplitterEditor.h index 6869c94ad584a99f683af4bba72d7f13d19c9f56..c3c4741ca909023abf2d83221ba0a2b37a2a3d44 100644 --- a/Source/Processors/Editors/SplitterEditor.h +++ b/Source/Processors/Editors/SplitterEditor.h @@ -35,14 +35,13 @@ // ~PipelineSelectorButton(); // }; -class SplitterEditor : public GenericEditor//, - // public Button::Listener +class SplitterEditor : public GenericEditor { public: SplitterEditor (GenericProcessor* parentNode); virtual ~SplitterEditor(); - void buttonClicked (Button* button); + void buttonEvent (Button* button); void switchDest(int); diff --git a/Source/Processors/Editors/VisualizerEditor.cpp b/Source/Processors/Editors/VisualizerEditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db474bbb2ec6a06e9c78c50a58d9aeb06bbd95a1 --- /dev/null +++ b/Source/Processors/Editors/VisualizerEditor.cpp @@ -0,0 +1,235 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "VisualizerEditor.h" + +SelectorButton::SelectorButton(const String& name_) + : Button(name_) +{ + setClickingTogglesState (true); + setTooltip ("Toggle a state."); + +} + +SelectorButton::~SelectorButton() +{ +} + +void SelectorButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown) +{ + if (getToggleState() == true) + g.setColour(Colours::white); + else + g.setColour(Colours::darkgrey); + + if (isMouseOver) + g.setColour(Colours::yellow); + + + if (getName().equalsIgnoreCase("window")) + { + // window icon + g.drawRect(0,0,getWidth(),getHeight(),1.0); + g.fillRect(0,0,getWidth(),3.0); + } else { + // tab icon + g.drawVerticalLine(5,0,getHeight()); + g.fillRoundedRectangle(5,2,4,getHeight()-4,4.0f); + g.fillRect(5,2,4,getHeight()-4); + } + +} + + +VisualizerEditor::VisualizerEditor (GenericProcessor* parentNode, int width) +: GenericEditor(parentNode), + tabIndex(-1), dataWindow(0), + isPlaying(false), + canvas(0), tabText("Tab") + +{ + + desiredWidth = width; + + initializeSelectors(); + +} + + +VisualizerEditor::VisualizerEditor (GenericProcessor* parentNode) + : GenericEditor(parentNode), + tabIndex(-1), dataWindow(0), + isPlaying(false), + canvas(0) + +{ + + desiredWidth = 250; + initializeSelectors(); + + +} +void VisualizerEditor::initializeSelectors(){ + + windowSelector = new SelectorButton("window"); + windowSelector->addListener(this); + windowSelector->setBounds(desiredWidth - 40,7,14,10); + + windowSelector->setToggleState(false,false); + addAndMakeVisible(windowSelector); + + tabSelector = new SelectorButton("tab"); + tabSelector->addListener(this); + tabSelector->setBounds(desiredWidth - 20,7,15,10); + + addAndMakeVisible(tabSelector); + tabSelector->setToggleState(false,false); +} + +VisualizerEditor::~VisualizerEditor() +{ + + if (tabIndex > -1) + { + getDataViewport()->removeTab(tabIndex); + } + + deleteAllChildren(); + +} + +void VisualizerEditor::enable() +{ + std::cout << " Enabling VisualizerEditor" << std::endl; + if (canvas != 0) + canvas->beginAnimation(); + + isPlaying = true; +} + +void VisualizerEditor::disable() +{ + if (canvas != 0) + canvas->endAnimation(); + + isPlaying = false; +} + +void VisualizerEditor::updateVisualizer() +{ + + if (canvas != 0) + canvas->update(); + +} + +void VisualizerEditor::buttonEvent(Button* button) +{ + + int gId = button->getRadioGroupId(); + + if (gId > 0) { + if (canvas != 0) + { + canvas->setParameter(gId-1, button->getName().getFloatValue()); + } + + } else { + + if (canvas == 0) { + + canvas = createNewCanvas(); + + if (isPlaying) + canvas->beginAnimation(); + } + + if (button == windowSelector) + { + + if (tabSelector->getToggleState() && windowSelector->getToggleState()) + { + tabSelector->setToggleState(false, false); + getDataViewport()->destroyTab(tabIndex); + tabIndex = -1; + } + + if (dataWindow == 0) { + + dataWindow = new DataWindow(windowSelector); + dataWindow->setContentNonOwned(canvas, false); + dataWindow->setVisible(true); + canvas->refreshState(); + + } else { + + dataWindow->setVisible(windowSelector->getToggleState()); + + if (windowSelector->getToggleState()) + { + dataWindow->setContentNonOwned(canvas, false); + canvas->refreshState(); + } else { + dataWindow->setContentNonOwned(0, false); + } + + } + + } + else if (button == tabSelector) + { + if (tabSelector->getToggleState() && tabIndex < 0) + { + + if (windowSelector->getToggleState()) + { + dataWindow->setContentNonOwned(0, false); + windowSelector->setToggleState(false, false); + dataWindow->setVisible(false); + } + + tabIndex = getDataViewport()->addTabToDataViewport(tabText,canvas); + + + } else if (!tabSelector->getToggleState() && tabIndex > -1) + { + getDataViewport()->destroyTab(tabIndex); + tabIndex = -1; + + } + } + + } + + buttonCallback(button); + + if (button == drawerButton) + { + std::cout<<"Drawer button clicked"<<std::endl; + windowSelector->setBounds(desiredWidth - 40,7,14,10); + tabSelector->setBounds(desiredWidth - 20,7,15,10); + + } + +} + diff --git a/Source/Processors/Editors/VisualizerEditor.h b/Source/Processors/Editors/VisualizerEditor.h new file mode 100644 index 0000000000000000000000000000000000000000..560fc51bfef910f294e515adcf36ca382ef48977 --- /dev/null +++ b/Source/Processors/Editors/VisualizerEditor.h @@ -0,0 +1,94 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef __VISUALIZEREDITOR_H_17E6D78C__ +#define __VISUALIZEREDITOR_H_17E6D78C__ + +#include "../../../JuceLibraryCode/JuceHeader.h" +#include "GenericEditor.h" +#include "../../UI/UIComponent.h" +#include "../../UI/DataViewport.h" +#include "../Visualization/DataWindow.h" +#include "../Visualization/Visualizer.h" + +/** + + Base class for creating editors with visualizers. + + @see GenericEditor, Visualizer + +*/ + +class DataWindow; +class Visualizer; + +class SelectorButton : public Button +{ + public: + SelectorButton(const String& name); + ~SelectorButton(); + private: + void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown); +}; + +class VisualizerEditor : public GenericEditor +{ +public: + VisualizerEditor (GenericProcessor*, int); + VisualizerEditor (GenericProcessor*); + ~VisualizerEditor(); + + void buttonEvent (Button* button); + virtual void buttonCallback(Button* button) {} + + virtual Visualizer* createNewCanvas() = 0; + + virtual void enable(); + virtual void disable(); + + void updateVisualizer(); + + ScopedPointer<DataWindow> dataWindow; + ScopedPointer<Visualizer> canvas; + + String tabText; + +private: + + void initializeSelectors(); + bool isPlaying; + + SelectorButton* windowSelector; + SelectorButton* tabSelector; + + int tabIndex; + + + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VisualizerEditor); + +}; + + + +#endif // __VISUALIZEREDITOR_H_17E6D78C__ diff --git a/Source/Processors/EventNode.cpp b/Source/Processors/EventNode.cpp index 67d365b478703c534219e399d1779bc92b3a2965..b36be29e73a6aa93391520d8b17e46d6faee1e11 100644 --- a/Source/Processors/EventNode.cpp +++ b/Source/Processors/EventNode.cpp @@ -27,11 +27,6 @@ EventNode::EventNode() : GenericProcessor("Event Generator"), Hz(1), accumulator(0) { - setNumOutputs(0); - setNumInputs(0); -// setSampleRate(44100.0); - - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); } @@ -42,30 +37,18 @@ EventNode::~EventNode() AudioProcessorEditor* EventNode::createEditor() { - EventNodeEditor* editor = new EventNodeEditor(this); - setEditor(editor); - - std::cout << "Creating editor." << std::endl; - //editor->setUIComponent(getUIComponent()); - //editor->setConfiguration(config); - - //filterEditor = new FilterEditor(this); + editor = new EventNodeEditor(this); return editor; - - //return 0; } - -bool EventNode::canSendSignalTo(GenericProcessor* p) +void EventNode::updateSettings() { - if (p->getName().equalsIgnoreCase("WiFi Output")) - { - return true; - } else { - return false; - } + // add event channels + settings.eventChannelIds.add(1); + settings.eventChannelNames.add("Trigger"); } + void EventNode::setParameter (int parameterIndex, float newValue) { std::cout << "Setting frequency to " << newValue << " Hz." << std::endl; @@ -86,11 +69,10 @@ void EventNode::process(AudioSampleBuffer &buffer, if (accumulator > getSampleRate()/Hz) { //std::cout << "Adding message." << std::endl; - addMidiEvent(midiMessages, 10, i); + addEvent(midiMessages, TTL, i); accumulator = 0; } } - } diff --git a/Source/Processors/EventNode.h b/Source/Processors/EventNode.h index 6d1491a0c207c019b3645b77099911d3ebb1441a..f0664849d04018c8476024f7601ebce6e47d3cc0 100644 --- a/Source/Processors/EventNode.h +++ b/Source/Processors/EventNode.h @@ -36,8 +36,6 @@ */ -class FilterViewport; - class EventNode : public GenericProcessor { @@ -50,11 +48,10 @@ public: void setParameter (int parameterIndex, float newValue); bool isSource() {return true;} - bool hasEditor() const {return true;} - float getSampleRate() {return 44100.0;} + int getDefaultNumOutputs() {return 0;} - bool canSendSignalTo(GenericProcessor*); + void updateSettings(); AudioProcessorEditor* createEditor(); diff --git a/Source/Processors/FileReader.cpp b/Source/Processors/FileReader.cpp deleted file mode 100644 index e0facd69406e3e149bc87def857cfc2df5d4bf6f..0000000000000000000000000000000000000000 --- a/Source/Processors/FileReader.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2012 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "FileReader.h" - - -FileReader::FileReader() - : GenericProcessor("File Reader"), - sampleRate (40000.0), - numChannels(16), - samplesPerBlock(1024) -{ - setNumOutputs(numChannels); - setNumInputs(0); -} - -FileReader::~FileReader() -{ -} - - -//AudioProcessorEditor* FileReader::createEditor( ) -//{ - //filterEditor = new FilterEditor(this); - -// std::cout << "Creating editor." << std::endl; -// sourceEditor = new SourceNodeEditor(this); -// return sourceEditor; -//} - - - -void FileReader::setParameter (int parameterIndex, float newValue) -{ - //std::cout << "Message received." << std::endl; -} - -bool FileReader::enable () { - - File file = File("./data_stream_16ch"); - input = file.createInputStream(); - - - std::cout << "File Reader received enable signal." << std::endl; - - return true; - -} - -bool FileReader::disable() { - - deleteAndZero(input); - - std::cout << "File reader received disable signal." << std::endl; - - return true; - -} - -void FileReader::process(AudioSampleBuffer &buffer, - MidiBuffer &midiMessages, - int& nSamples) -{ - - nSamples = samplesPerBlock; - //std::cout << buffer.getNumChannels() << std::endl; - - for (int i = 0; i < samplesPerBlock; ++i) - { - - for (int j = 0; j < numChannels; j++) { - - if (input->isExhausted()) - input->setPosition(0); - - const float sample = float(input->readShort()); - - *buffer.getSampleData (j, i) = sample; - } - - } -} \ No newline at end of file diff --git a/Source/Processors/FileReader.h b/Source/Processors/FileReader.h deleted file mode 100644 index 30394bdd3bbef20564c6dfe04c05c685c4b5d6d0..0000000000000000000000000000000000000000 --- a/Source/Processors/FileReader.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2012 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef __FILEREADER_H_605BF4A__ -#define __FILEREADER_H_605BF4A__ - - -#include "../../JuceLibraryCode/JuceHeader.h" -#include "GenericProcessor.h" - -/** - - --UNDER CONSTRUCTION-- - - Reads data from a file with a specific format. - - @see GenericProcessor - -*/ - - -class FileReader : public GenericProcessor - -{ -public: - - // real member functions: - FileReader(); - ~FileReader(); - - void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples); - - void setParameter (int parameterIndex, float newValue); - - //AudioProcessorEditor* createEditor(); - bool hasEditor() const {return true;} - - bool enable(); - bool disable(); - - bool isSource() {return true;} - -private: - - float sampleRate; - int numChannels; - int samplesPerBlock; - - FileInputStream* input; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileReader); - -}; - - - - -#endif // __FILEREADER_H_605BF4A__ diff --git a/Source/Processors/FilterNode.cpp b/Source/Processors/FilterNode.cpp index fd8fb9e55d9f4ead7ec1905a0316664c98a29d71..e381b58ea7f1e7b83da1d04ae20c465afab3d556 100644 --- a/Source/Processors/FilterNode.cpp +++ b/Source/Processors/FilterNode.cpp @@ -39,12 +39,12 @@ FilterNode::~FilterNode() AudioProcessorEditor* FilterNode::createEditor() { - FilterEditor* filterEditor = new FilterEditor(this); - setEditor(filterEditor); + editor = new FilterEditor(this); + //setEditor(filterEditor); std::cout << "Creating editor." << std::endl; - return filterEditor; + return editor; } @@ -81,51 +81,34 @@ AudioProcessorEditor* FilterNode::createEditor() // necessary to interoperate with the Filter virtual base class and its derived classes -void FilterNode::setNumInputs(int inputs) +void FilterNode::updateSettings() { - numInputs = inputs; - setNumOutputs(inputs); - filters.clear(); lowCuts.clear(); highCuts.clear(); - if (inputs < 100) { - - for (int n = 0; n < getNumInputs(); n++) - { - std::cout << "Creating filter number " << n << std::endl; - - filters.add(new Dsp::SmoothedFilterDesign - <Dsp::Butterworth::Design::BandPass // design type - <4>, // order - 1, // number of channels (must be const) - Dsp::DirectFormII> // realization - (1024)); - - lowCuts.add(1.0f); - highCuts.add(1000.0f); - - setFilterParameters(1.0f, 1000.0f, n); - } - - } - -} - -void FilterNode::setSampleRate(float r) -{ - sampleRate = r; - - if (numInputs < 100) { + if (getNumInputs() < 100) { for (int n = 0; n < getNumInputs(); n++) { - setFilterParameters(lowCuts[n], highCuts[n], n); + std::cout << "Creating filter number " << n << std::endl; + + filters.add(new Dsp::SmoothedFilterDesign + <Dsp::Butterworth::Design::BandPass // design type + <4>, // order + 1, // number of channels (must be const) + Dsp::DirectFormII> // realization + (1024)); + + lowCuts.add(1.0f); + highCuts.add(1000.0f); + + setFilterParameters(1.0f, 1000.0f, n); } + } - + } void FilterNode::setFilterParameters(double lowCut, double highCut, int chan) diff --git a/Source/Processors/FilterNode.h b/Source/Processors/FilterNode.h index 2a6e616477d13d6b4eb18822254ee47d35a3caba..1dbe3fbd025385f56c26b3978c0a49a1f34dbf0c 100644 --- a/Source/Processors/FilterNode.h +++ b/Source/Processors/FilterNode.h @@ -52,9 +52,8 @@ public: AudioProcessorEditor* createEditor(); bool hasEditor() const {return true;} - - void setNumInputs(int); - void setSampleRate(float); + + void updateSettings(); private: diff --git a/Source/Processors/GenericProcessor.cpp b/Source/Processors/GenericProcessor.cpp index 385d8a8d85afa3111ea89d31552806bbca339a07..16f70eb2f9c7aa75b5aac1ee87e5cfbfe67e2b61 100644 --- a/Source/Processors/GenericProcessor.cpp +++ b/Source/Processors/GenericProcessor.cpp @@ -24,20 +24,18 @@ #include "GenericProcessor.h" #include "../UI/UIComponent.h" -GenericProcessor::GenericProcessor(const String& name_) : name(name_), - sourceNode(0), destNode(0), editor(0), isEnabled(true), saveOrder(-1), loadOrder(-1), - nextAvailableChannel(0), wasConnected(false), currentChannel(-1) - +GenericProcessor::GenericProcessor(const String& name_) : + name(name_), + sourceNode(0), destNode(0), + isEnabled(true), + saveOrder(-1), loadOrder(-1), + nextAvailableChannel(0), currentChannel(-1), + wasConnected(false) { - } GenericProcessor::~GenericProcessor() { - if (editor != 0) - { - deleteAndZero(editor); - } } AudioProcessorEditor* GenericProcessor::createEditor() @@ -49,44 +47,26 @@ AudioProcessorEditor* GenericProcessor::createEditor() void GenericProcessor::setParameter (int parameterIndex, float newValue) { - + if (currentChannel > 0) + { + //Parameter& p = parameters[parameterIndex]; + //parameters[parameterIndex].setValue(newValue, currentChannel); + } } -GenericProcessor* GenericProcessor::getOriginalSourceNode() +const String GenericProcessor::getParameterName (int parameterIndex) { - if (isSource()) - { - return this; - } else { - - GenericProcessor* source = getSourceNode(); - - if (source != 0) - { - while (!source->isSource() && source != 0) - { - source = source->getSourceNode(); - } - - return source; - - } else { - return 0; - } - } + //Parameter& p = parameters[parameterIndex]; + //return parameters[parameterIndex].getName(); } -int GenericProcessor::getDefaultNumOutputs() +const String GenericProcessor::getParameterText (int parameterIndex) { - if (!isSink()) - { - return 10; - } else { - return 0; - } + //Parameter& p = parameters[parameterIndex]; + //return parameters[parameterIndex].getDescription(); } - + void GenericProcessor::prepareToPlay (double sampleRate_, int estimatedSamplesPerBlock) { @@ -102,21 +82,12 @@ void GenericProcessor::releaseResources() // disable() is only called by the ProcessorGraph at the end of acquisition } - -// void GenericProcessor::sendMessage(const String& msg) -// { -// std::cout << "Message: "; -// std::cout << msg << "...." << std::endl; -// UI->transmitMessage(msg); -// } - - int GenericProcessor::getNextChannel(bool increment) { int chan = nextAvailableChannel; //std::cout << chan << std::endl; - + if (increment) nextAvailableChannel++; @@ -134,43 +105,42 @@ void GenericProcessor::resetConnections() wasConnected = false; } -void GenericProcessor::setNumSamples(MidiBuffer& midiMessages, int numberToAdd) { +void GenericProcessor::setNumSamples(MidiBuffer& events, int sampleIndex) { uint8 data[2]; - data[0] = numberToAdd >> 8; // most-significant byte - data[1] = numberToAdd & 0xFF; // least-significant byte - - midiMessages.addEvent(data, // spike data - sizeof(data), // total bytes - -1); // sample index + data[0] = BUFFER_SIZE; // most-significant byte + data[1] = nodeId; // least-significant byte + events.addEvent(data, // spike data + 2, // total bytes + sampleIndex); // sample index } -int GenericProcessor::getNumSamples(MidiBuffer& midiMessages) { +int GenericProcessor::getNumSamples(MidiBuffer& events) { int numRead = 0; - if (midiMessages.getNumEvents() > 0) + if (events.getNumEvents() > 0) { - int m = midiMessages.getNumEvents(); + int m = events.getNumEvents(); - MidiBuffer::Iterator i (midiMessages); + MidiBuffer::Iterator i (events); MidiMessage message(0xf4); int samplePosition = -5; while (i.getNextEvent (message, samplePosition)) { - int numbytes = message.getRawDataSize(); - uint8* dataptr = message.getRawData(); + uint8* dataptr = message.getRawData(); - if (message.getTimeStamp() < 0) - numRead = (*dataptr<<8) + *(dataptr+1); + if (*dataptr == BUFFER_SIZE) + { + numRead = message.getTimeStamp(); + } } - } return numRead; @@ -279,80 +249,86 @@ void GenericProcessor::setDestNode(GenericProcessor* dn) } } -void GenericProcessor::updateSettings() +void GenericProcessor::clearSettings() +{ + settings.originalSource = 0; + settings.numInputs = 0; + settings.numOutputs = 0; + settings.inputChannelNames.clear(); + settings.outputChannelNames.clear(); + settings.bitVolts.clear(); + settings.eventChannelIds.clear(); + settings.eventChannelNames.clear(); +} + +void GenericProcessor::update() { + + std::cout << getName() << " updating settings." << std::endl; + + clearSettings(); if (sourceNode != 0) { - setSampleRate(sourceNode->getSampleRate()); - setNumInputs(sourceNode->getNumOutputs()); + // everything is inherited except numOutputs + settings = sourceNode->settings; + settings.numInputs = settings.numOutputs; + settings.numOutputs = settings.numInputs; + } else { - setSampleRate(getDefaultSampleRate()); - setNumInputs(0); - setNumOutputs(getDefaultNumOutputs()); - } - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); + settings.sampleRate = getDefaultSampleRate(); + settings.numOutputs = getDefaultNumOutputs(); - updateParameters(); + for (int i = 0; i < getNumOutputs(); i++) + settings.bitVolts.add(getDefaultBitVolts()); - GenericEditor* editor = (GenericEditor*) getEditor(); + generateDefaultChannelNames(settings.outputChannelNames); - editor->update(); + } -} + if (this->isSink()) + { + settings.numOutputs = 0; + settings.outputChannelNames.clear(); + } -void GenericProcessor::updateParameters() -{ - -} + updateSettings(); // custom settings code + // required for the ProcessorGraph to know the + // details of this processor: + setPlayConfigDetails(getNumInputs(), // numIns + getNumOutputs(), // numOuts + 44100.0, // sampleRate + 128); // blockSize + + editor->update(); // update editor settings -int GenericProcessor::getNumInputs() -{ - return numInputs; } -int GenericProcessor::getNumOutputs() +bool GenericProcessor::recordStatus(int chan) { - return numOutputs; -} -void GenericProcessor::setNumInputs(int n) { - numInputs = n; - // if (destNode != 0) - // { - // destNode->setNumInputs(); - // } - //setPlayConfigDetails(numInputs,numOutputs,44100.0,1024); -} + return getEditor()->recordChannels[chan]; + -void GenericProcessor::setNumInputs() { - - int n = getSourceNode()->getNumOutputs(); - setNumInputs(n); } -void GenericProcessor::setNumOutputs() +void GenericProcessor::generateDefaultChannelNames(StringArray& names) { - setNumOutputs(getNumInputs()); -} + names.clear(); -void GenericProcessor::setNumOutputs(int n) { - numOutputs = n; - //setPlayConfigDetails(numInputs,numOutputs,44100.0,1024); -} + for (int i = 0; i < settings.numOutputs; i++) + { + String channelName = "CH"; + channelName += (i+1); + names.add(channelName); + } -float GenericProcessor::getSampleRate() -{ - return sampleRate; -} -void GenericProcessor::setSampleRate(float sr) -{ - sampleRate = sr; } -int GenericProcessor::checkForMidiEvents(MidiBuffer& midiMessages) + +int GenericProcessor::checkForEvents(MidiBuffer& midiMessages) { if (midiMessages.getNumEvents() > 0) @@ -369,18 +345,10 @@ int GenericProcessor::checkForMidiEvents(MidiBuffer& midiMessages) while (i.getNextEvent (message, samplePosition)) { - int numbytes = message.getRawDataSize(); - uint8* dataptr = message.getRawData(); + uint8* dataptr = message.getRawData(); - //std::cout << " Bytes received: " << numbytes << std::endl; - //std::cout << " Message timestamp = " << message.getTimeStamp() << std::endl; + handleEvent(*dataptr, message); - if (message.getTimeStamp() >= 0) - { - int value = (*dataptr<<8) + *(dataptr+1); - //std::cout << " " << value << std::endl; - return value; - } } } @@ -389,26 +357,35 @@ int GenericProcessor::checkForMidiEvents(MidiBuffer& midiMessages) } -void GenericProcessor::addMidiEvent(MidiBuffer& midiMessages, int numberToAdd, int sampleNum) +void GenericProcessor::addEvent(MidiBuffer& eventBuffer, + uint8 type, + int sampleNum, + uint8 eventId, + uint8 eventChannel, + uint8 numBytes, + uint8* eventData) { - uint8 data[2]; + uint8 data[4+numBytes]; - data[0] = numberToAdd >> 8; // most-significant byte - data[1] = numberToAdd & 0xFF; // least-significant byte + data[0] = type; // event type + data[1] = nodeId; // processor ID + data[2] = eventId; // event ID + data[3] = eventChannel; // event channel + memcpy(&data[4], eventData, numBytes); - midiMessages.addEvent(data, // spike data + eventBuffer.addEvent(data, // spike data sizeof(data), // total bytes sampleNum); // sample index } -void GenericProcessor::processBlock (AudioSampleBuffer &buffer, MidiBuffer &midiMessages) +void GenericProcessor::processBlock (AudioSampleBuffer &buffer, MidiBuffer &eventBuffer) { - int nSamples = getNumSamples(midiMessages); // removes first value from midimessages + int nSamples = getNumSamples(eventBuffer); // removes first value from midimessages - process(buffer, midiMessages, nSamples); + process(buffer, eventBuffer, nSamples); - setNumSamples(midiMessages, nSamples); // adds it back, - // even if it's unchanged + setNumSamples(eventBuffer, nSamples); // adds it back, + // even if it's unchanged } diff --git a/Source/Processors/GenericProcessor.h b/Source/Processors/GenericProcessor.h index 1612abe31703ec09ba94ce1a219f3672d5f59980..8e1a3e4e3763e716dbfc591e0f428d789c10abf9 100644 --- a/Source/Processors/GenericProcessor.h +++ b/Source/Processors/GenericProcessor.h @@ -27,8 +27,9 @@ #include "../../JuceLibraryCode/JuceHeader.h" #include "Editors/GenericEditor.h" -#include "../UI/Configuration.h" +#include "Parameter.h" #include "../AccessClass.h" + #include <time.h> #include <stdio.h> @@ -49,9 +50,10 @@ class EditorViewport; class DataViewport; class UIComponent; +class GenericEditor; +//class Parameter; class GenericProcessor : public AudioProcessor, - // public ActionBroadcaster, public AccessClass { @@ -81,11 +83,11 @@ public: void changeProgramName (int index, const String &newName) {} void setCurrentProgram (int index) {} - const String getInputChannelName (int channelIndex) const {return T(" ");} - const String getOutputChannelName (int channelIndex) const {return T(" ");} - const String getParameterName (int parameterIndex) {return T(" ");} - const String getParameterText (int parameterIndex) {return T(" ");} - const String getProgramName (int index) {return T(" ");} + const String getInputChannelName (int channelIndex) const {return settings.inputChannelNames[channelIndex];} + const String getOutputChannelName (int channelIndex) const {return settings.outputChannelNames[channelIndex];} + const String getParameterName (int parameterIndex); //{return parameters[parameterIndex]->getName();} + const String getParameterText (int parameterIndex); //{return parameters[parameterIndex]->getDescription();} + const String getProgramName (int index) {return "";} bool isInputChannelStereoPair (int index) const {return true;} bool isOutputChannelStereoPair (int index) const {return true;} @@ -95,11 +97,12 @@ public: bool isParameterAutomatable(int parameterIndex) {return false;} bool isMetaParameter(int parameterIndex) {return false;} - int getNumParameters() {return 0;} + int getNumParameters() {return parameters.size();} int getNumPrograms() {return 0;} int getCurrentProgram() {return 0;} float getParameter (int parameterIndex) {return 1.0;} + Parameter& getParameterByName(String parameterName); //---------------------------------------------------------------------- // Custom methods: @@ -109,37 +112,22 @@ public: MidiBuffer& /*buffer*/, int& /*nSamples*/) = 0; - - GenericProcessor* sourceNode; GenericProcessor* destNode; - int numInputs; - int numOutputs; - - float sampleRate; - - //void sendMessage(const String& msg); - - virtual float getSampleRate(); - virtual void setSampleRate(float sr); + virtual float getSampleRate() {return settings.sampleRate;} virtual float getDefaultSampleRate() {return 44100.0;} - virtual int getNumInputs(); - virtual void setNumInputs(int); - virtual void setNumInputs(); - - virtual int getNumOutputs(); - virtual void setNumOutputs(int); - virtual void setNumOutputs(); - virtual int getDefaultNumOutputs(); + virtual int getNumInputs() {return settings.numInputs;} + virtual int getNumOutputs() {return settings.numOutputs;} + virtual int getDefaultNumOutputs() {return 2;} + + //virtual float getBitVolts() {return settings.bitVolts;} + virtual float getDefaultBitVolts() {return 1.0;} virtual int getNextChannel(bool); virtual void resetConnections(); - virtual void updateSettings(); // updates sample rate and number of channels - virtual void updateParameters(); // called in updateSettings() to update params - virtual void setCurrentChannel(int chan) {currentChannel = chan;} int getNodeId() {return nodeId;} @@ -148,12 +136,9 @@ public: // get/set source node functions GenericProcessor* getSourceNode() {return sourceNode;} GenericProcessor* getDestNode() {return destNode;} - GenericProcessor* getOriginalSourceNode(); - virtual void switchSource(int) { }; - virtual void switchSource() { }; - virtual void switchDest() { }; - virtual void switchDest(int) { }; + virtual void switchIO(int) { }; + virtual void switchIO() { }; virtual void setSourceNode(GenericProcessor* sn); virtual void setDestNode(GenericProcessor* dn); @@ -176,59 +161,84 @@ public: virtual bool stillHasSource() {return true;} + bool isEnabled; + bool wasConnected; + virtual AudioSampleBuffer* getContinuousBuffer() {return 0;} virtual MidiBuffer* getEventBuffer() {return 0;} int nextAvailableChannel; - int checkForMidiEvents(MidiBuffer& mb); - void addMidiEvent(MidiBuffer& mb, int a, int b); - - bool isEnabled; - - bool wasConnected; + // event buffers + virtual int checkForEvents(MidiBuffer& mb); + virtual void addEvent(MidiBuffer& mb, + uint8 type, + int sampleNum, + uint8 eventID = 0, + uint8 eventChannel = 0, + uint8 numBytes = 0, + uint8* data = 0); + + virtual void handleEvent(int eventType, MidiMessage& event) {} + + enum eventTypes + { + TIMESTAMP = 0, + BUFFER_SIZE = 1, + PARAMETER_CHANGE = 2, + TTL = 3, + SPIKE = 4, + EEG = 5, + CONTINUOUS = 6 + }; int saveOrder; int loadOrder; int currentChannel; + virtual GenericEditor* getEditor() {return editor;} + ScopedPointer<GenericEditor> editor; - // Getting and setting: + struct ProcessorSettings { - AudioProcessorEditor* getEditor() {return editor;} - void setEditor(AudioProcessorEditor* e) {editor = e;} + GenericProcessor* originalSource; - // void setUIComponent(UIComponent* ui) {UI = ui;} - // UIComponent* getUIComponent() {return UI;} + int numInputs; + int numOutputs; + StringArray inputChannelNames; + StringArray outputChannelNames; - // virtual void setConfiguration(Configuration* cf) {config = cf;} - // Configuration* getConfiguration() {return config;} + float sampleRate; + Array<float> bitVolts; - // void setFilterViewport(FilterViewport* vp) {viewport = vp;} - // FilterViewport* getFilterViewport() {return viewport;} + Array<int> eventChannelIds; + StringArray eventChannelNames; - // void setDataViewport(DataViewport* dv) {dataViewport = dv;} - // DataViewport* getDataViewport() {return dataViewport;} + }; + ProcessorSettings settings; - //FilterViewport* viewport; - //DataViewport* dataViewport; - //UIComponent* UI; + virtual bool recordStatus(int chan); - //Configuration* config; + virtual void clearSettings(); - //int tabA, tabB; // needed for Merger + virtual void generateDefaultChannelNames(StringArray&); - AudioProcessorEditor* editor; + virtual void update(); // default node updating + virtual void updateSettings() {} // custom node updating + + int nodeId; + + // parameters: + Array<Parameter> parameters; + StringArray parameterNames; private: void processBlock (AudioSampleBuffer &buffer, MidiBuffer &midiMessages); const String name; - - int nodeId; int getNumSamples(MidiBuffer&); void setNumSamples(MidiBuffer&, int); diff --git a/Source/Processors/LfpDisplayNode.cpp b/Source/Processors/LfpDisplayNode.cpp index 09935130a9b80c809756fbed06674ddf2c47cfb1..c444d776a51e218e684a9581cf80c1bcde91c82d 100644 --- a/Source/Processors/LfpDisplayNode.cpp +++ b/Source/Processors/LfpDisplayNode.cpp @@ -30,64 +30,32 @@ LfpDisplayNode::LfpDisplayNode() displayBufferIndex(0), abstractFifo(100) { - - numInputs = 2; - numOutputs = 0; - sampleRate = 44100.0; - - setPlayConfigDetails(2,0,44100.0,128); - - displayBuffer = new AudioSampleBuffer (8, 100); + displayBuffer = new AudioSampleBuffer(8, 100); eventBuffer = new MidiBuffer(); } LfpDisplayNode::~LfpDisplayNode() { - - deleteAndZero(displayBuffer); - deleteAndZero(eventBuffer); + //deleteAndZero(displayBuffer); + //deleteAndZero(eventBuffer); } AudioProcessorEditor* LfpDisplayNode::createEditor() { - LfpDisplayEditor* editor = new LfpDisplayEditor(this); - - //editor->setBuffers (displayBuffer, eventBuffer); - //editor->setUIComponent (getUIComponent()); - //editor->setConfiguration (config); - //editor->updateNumInputs(getNumInputs()); - //editor->updateSampleRate(sampleRate); - - setEditor(editor); - + editor = new LfpDisplayEditor(this); return editor; } -void LfpDisplayNode::setNumInputs(int inputs) +void LfpDisplayNode::updateSettings() { - std::cout << "Setting num inputs on LfpDisplayNode to " << inputs << std::endl; - numInputs = inputs; - setNumOutputs(0); - - setPlayConfigDetails(getNumInputs(),0,44100.0,128); - - LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor(); - editor->updateNumInputs(inputs); -} - -void LfpDisplayNode::setSampleRate(float r) -{ - sampleRate = r; - - LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor(); - editor->updateSampleRate(r); + std::cout << "Setting num inputs on LfpDisplayNode to " << getNumInputs() << std::endl; } bool LfpDisplayNode::resizeBuffer() { - int nSamples = (int) sampleRate*bufferLength; + int nSamples = (int) getSampleRate()*bufferLength; int nInputs = getNumInputs(); std::cout << "Resizing buffer. Samples: " << nSamples << ", Inputs: " << nInputs << std::endl; @@ -132,6 +100,7 @@ void LfpDisplayNode::setParameter (int parameterIndex, float newValue) void LfpDisplayNode::process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples) { // 1. place any new samples into the displayBuffer + int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex; if (nSamples < samplesLeft) diff --git a/Source/Processors/LfpDisplayNode.h b/Source/Processors/LfpDisplayNode.h index a0555542c33170cf6b61d61973309558e84c5a83..8fb4439cd9614e7ed5b8998cd00b6c7c3dcee0db 100644 --- a/Source/Processors/LfpDisplayNode.h +++ b/Source/Processors/LfpDisplayNode.h @@ -26,6 +26,7 @@ #include "../../JuceLibraryCode/JuceHeader.h" #include "Editors/LfpDisplayEditor.h" +#include "Editors/VisualizerEditor.h" #include "GenericProcessor.h" /** @@ -56,8 +57,7 @@ public: void setParameter(int, float); - void setNumInputs(int inputs); - void setSampleRate(float r); + void updateSettings(); bool enable(); bool disable(); @@ -67,10 +67,8 @@ public: private: - DataViewport* dataViewport; - - AudioSampleBuffer* displayBuffer; - MidiBuffer* eventBuffer; + ScopedPointer<AudioSampleBuffer> displayBuffer; + ScopedPointer<MidiBuffer> eventBuffer; int displayBufferIndex; diff --git a/Source/Processors/Parameter.cpp b/Source/Processors/Parameter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d68d52698f9b01ed637dbd326888d2b04a0c9824 --- /dev/null +++ b/Source/Processors/Parameter.cpp @@ -0,0 +1,203 @@ + +/* ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "Parameter.h" + + +Parameter::Parameter(const String& name_, bool defaultVal) + : name(name_), description("") +{ + + defaultValue = defaultVal; + + possibleValues.add(true); + possibleValues.add(false); + + isBool = true; + isCont = false; + isDisc = false; + +} + +Parameter::Parameter(const String& name_, float low, float high, float defaultVal) + : name(name_), description("") +{ + defaultValue = defaultVal; + + possibleValues.add(low); + possibleValues.add(high); + + isCont = true; + isBool = false; + isDisc = false; + +} + +Parameter::Parameter(const String& name_, Array<var> a, int defaultVal) + : name(name_), description("") +{ + possibleValues = a; + defaultValue = possibleValues[defaultVal]; + + isCont = false; + isDisc = true; + isBool = false; + +} + + +void Parameter::setValue(float val, int chan) +{ + if (isBoolean()) + { + if (val > 0.0f) + values.set(chan, true); + else + values.set(chan, false); + } + else if (isContinuous()) { + + if (val < (float) possibleValues[0]) + { + values.set(chan, possibleValues[0]); + } else if (val > (float) possibleValues[1]) { + values.set(chan, possibleValues[1]); + } else { + values.set(chan, val); + } + + } else { + int index = (int) val; + + if (index >= 0 && index < possibleValues.size()) + { + values.set(chan, possibleValues[index]); + } + + } + +} + +// void BooleanParameter::setValue(float val, int chan) +// { + +// var b = true; +// bool c = b; + +// if (val > 0) +// values.set(chan, true); +// else +// values.set(chan, false); + +// } + +// void ContinuousParameter::setValue(float val, int chan) +// { +// if (val < low) +// { +// values.set(chan, low); +// } else if (val > high) { +// values.set(chan, high); +// } else { +// values.set(chan, val); +// } +// } + +// void DiscreteParameter::setValue(float val, int chan) +// { +// int index = (int) val; + +// if (index >= 0 && index < possibleValues.size()) +// { +// values.set(chan, possibleValues[index]); +// } + +// } + +// Array<var> BooleanParameter::getPossibleValues() +// { +// Array<var> a; +// a.add(true); +// a.add(false); + +// return a; + +// } + +// Array<var> ContinuousParameter::getPossibleValues() +// { +// Array<var> a; +// a.add(low); +// a.add(high); + +// return a; +// } + +// Array<var> DiscreteParameter::getPossibleValues() +// { +// return possibleValues; + +// } + + +// void* BooleanParameter::operator[](int chan) +// { +// return (void*) values[chan]; +// } + +// void* ContinuousParameter::operator[](int chan) +// { +// return (void*) values[chan]; +// } + + +// void* DiscreteParameter::operator[](int chan) +// { +// return (void*) values[chan]; +// } + +// BooleanParameter::BooleanParameter(const String name_, bool defaultVal) : Parameter(name_) +// { +// defaultValue = defaultVal; +// } + +// ContinuousParameter::ContinuousParameter(const String name_, +// float low_, float high_, float defaultVal) +// : Parameter(name_) +// { +// low = low_; +// high = high_; + +// defaultValue = defaultVal; + +// } + +// DiscreteParameter::DiscreteParameter(const String name_, +// Array<var> a, int defaultVal) +// : Parameter(name_) +// { +// possibleValues = a; + +// defaultValue = possibleValues[defaultVal]; +// } + diff --git a/Source/Processors/Parameter.h b/Source/Processors/Parameter.h new file mode 100644 index 0000000000000000000000000000000000000000..89a2c352e13cffa27934af2e0a3d1ff2f93f320c --- /dev/null +++ b/Source/Processors/Parameter.h @@ -0,0 +1,161 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef __PARAMETER_H_62922AE5__ +#define __PARAMETER_H_62922AE5__ + +#include "../../JuceLibraryCode/JuceHeader.h" +// #include "Editors/GenericEditor.h" +// #include "GenericProcessor.h" +// #include "../AccessClass.h" + +#include <stdio.h> + +/** + + Class for holding user-definable processor parameters. + + @see GenericProcessor, GenericEditor + +*/ + +class Parameter +{ +public: + + Parameter(const String& name_, bool defaultVal); + Parameter(const String& name_, float low, float high, float defaultVal); + Parameter(const String& name_, Array<var> a, int defaultVal); + + ~Parameter() {} + + const String& getName() {return name;} + const String& getDescription() {return description;} + void addDescription(const String& desc) {description = desc;} + + Array<var> getPossibleValues() {return possibleValues;} + void setValue(float val, int chan); + + var operator[](int chan) {return values[chan];} + Parameter& operator=(const Parameter& other); + + bool isBoolean() {return isBool;} + bool isContinuous() {return isCont;} + bool isDiscrete() {return isDisc;} + +private: + + + const String name; + String description; + + bool isBool, isCont, isDisc; + + var defaultValue; + Array<var> values; + Array<var> possibleValues; + +}; + +// class BooleanParameter : public Parameter +// { +// public: +// BooleanParameter(const String name_, bool defaultVal); +// ~BooleanParameter() {} + +// Array<var> getPossibleValues(); +// void setValue(float val, int chan); +// void* operator[](int chan); + +// bool isBoolean() {return true;} + +// bool defaultValue; + +// Array<bool> values; + +// }; + +// class ContinuousParameter : public Parameter +// { +// public: +// ContinuousParameter(const String name_, float low, float high, float defaultVal); +// ~ContinuousParameter() {} + +// Array<var> getPossibleValues(); +// void setValue(float val, int chan); +// void* operator[](int chan); + +// bool isContinuous() {return true;} + +// float low, high, defaultValue; + +// Array<float> values; + +// }; + + +// class DiscreteParameter : public Parameter +// { +// public: +// DiscreteParameter(const String name_, Array<var> a, int defaultVal); +// ~DiscreteParameter() {} + +// Array<var> getPossibleValues(); +// void setValue(float val, int chan); +// void* operator[](int chan); + +// bool isDiscrete() {return true;} + +// Array<var> possibleValues; +// Array<var> values; + +// int defaultValue; +// }; + + +// template <class Type> + +// class Parameter +// { +// public: +// Parameter(const String& name_, +// Type defaultVal, +// Array<var> possibleVals = Array<var>()) : +// name(name_), defaultValue(defaultVal), possibleValues(possibleVals) +// { + +// } + +// Type operator[](int chan) {return values[chan];} + +// private: + +// const String name; +// Type defaultValue; +// Array<Type> values; +// Array<var> possibleValues; + +// }; + + +#endif // __PARAMETER_H_62922AE5__ diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp index ce3c7717aa5a2f21260ecda27de066548fd0313b..b690742cd4c8d816e04c9b313da5954c7f0a0de2 100644 --- a/Source/Processors/ProcessorGraph.cpp +++ b/Source/Processors/ProcessorGraph.cpp @@ -27,8 +27,8 @@ #include "AudioNode.h" #include "LfpDisplayNode.h" +#include "SpikeDisplayNode.h" #include "EventNode.h" -#include "FileReader.h" #include "FilterNode.h" #include "GenericProcessor.h" #include "RecordNode.h" @@ -40,21 +40,12 @@ #include "Utilities/Splitter.h" #include "Utilities/Merger.h" #include "../UI/UIComponent.h" -#include "../UI/Configuration.h" #include "../UI/EditorViewport.h" -ProcessorGraph::ProcessorGraph() : - currentNodeId(100), - RECORD_NODE_ID(199), - AUDIO_NODE_ID(200), - OUTPUT_NODE_ID(201), - RESAMPLING_NODE_ID(202) - //totalAudioConnections(0), - //totalRecordConnections(0) - +ProcessorGraph::ProcessorGraph() : currentNodeId(100) { - // ProcessorGraph will always have 0 inputs (all content is generated within graph) + // The ProcessorGraph will always have 0 inputs (all content is generated within graph) // but it will have N outputs, where N is the number of channels for the audio monitor setPlayConfigDetails(0, // number of inputs 2, // number of outputs @@ -78,12 +69,10 @@ void ProcessorGraph::createDefaultNodes() // add record node -- sends output to disk RecordNode* recn = new RecordNode(); recn->setNodeId(RECORD_NODE_ID); - //recn->setConfiguration(config); // add audio node -- takes all inputs and selects those to be used for audio monitoring AudioNode* an = new AudioNode(); recn->setNodeId(AUDIO_NODE_ID); - //an->setConfiguration(config); // add resampling node -- resamples continuous signals to 44.1kHz ResamplingNode* rn = new ResamplingNode(true); @@ -94,7 +83,7 @@ void ProcessorGraph::createDefaultNodes() addNode(an, AUDIO_NODE_ID); addNode(rn, RESAMPLING_NODE_ID); - // connect audio network + // connect audio subnetwork for (int n = 0; n < 2; n++) { addConnection(AUDIO_NODE_ID, n, @@ -150,22 +139,22 @@ void ProcessorGraph::clearConnections() { ; // leave it } else { - - Node* node = getNodeForId(connection->sourceNodeId); - GenericProcessor* p =(GenericProcessor*) node->getProcessor(); - //if (p->getNextChannel(false) > 0) - p->resetConnections(); - - node = getNodeForId(connection->destNodeId); - p =(GenericProcessor*) node->getProcessor(); - //if (p->getNextChannel(false) > 0) - p->resetConnections(); - removeConnection(i); } } + + for (int i = 0; i < getNumNodes(); i++) + { + Node* node = getNode(i); + + if (node->nodeId != OUTPUT_NODE_ID) { + GenericProcessor* p =(GenericProcessor*) node->getProcessor(); + p->resetConnections(); + } + } } + void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSection> tabs) { clearConnections(); // clear processor graph @@ -208,8 +197,6 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect { // add the connections to audio and record nodes if necessary - - if (!(source->isSink() || source->isSplitter() || source->isMerger()) && !(source->wasConnected)) { @@ -217,18 +204,38 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect for (int chan = 0; chan < source->getNumOutputs(); chan++) { - addConnection(source->getNodeId(), // sourceNodeID - chan, // sourceNodeChannelIndex - AUDIO_NODE_ID, // destNodeID + //getAudioNode()->addInputChannel(source, chan); + + addConnection(source->getNodeId(), // sourceNodeID + chan, // sourceNodeChannelIndex + AUDIO_NODE_ID, // destNodeID getAudioNode()->getNextChannel(true)); // destNodeChannelIndex - addConnection(source->getNodeId(), // sourceNodeID - chan, // sourceNodeChannelIndex - RECORD_NODE_ID, // destNodeID + + //std::cout << getAudioNode()->getNextChannel(false) << " "; + + getRecordNode()->addInputChannel(source, chan); + + addConnection(source->getNodeId(), // sourceNodeID + chan, // sourceNodeChannelIndex + RECORD_NODE_ID, // destNodeID getRecordNode()->getNextChannel(true)); // destNodeChannelIndex + + } + + // connect event channel + addConnection(source->getNodeId(), // sourceNodeID + midiChannelIndex, // sourceNodeChannelIndex + RECORD_NODE_ID, // destNodeID + midiChannelIndex); // destNodeChannelIndex + + getRecordNode()->addInputChannel(source, midiChannelIndex); + } + std::cout << std::endl; + if (dest != 0) { if (dest->enabledState()) @@ -241,12 +248,7 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect std::cout << " Connecting " << source->getName() << " channel "; - //int nextChan; - //int chan = 0; - for (int chan = 0; chan < source->getNumOutputs(); chan++) - - //ile ((nextChan = dest->getNextChannel(true)) != -1) { std::cout << chan << " "; @@ -258,14 +260,15 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect std::cout << " to " << dest->getName() << std::endl; - std::cout << " Connecting " << source->getName() << - " event channel to " << - dest->getName() << std::endl; - // connect event channel - addConnection(source->getNodeId(), // sourceNodeID - midiChannelIndex, // sourceNodeChannelIndex - dest->getNodeId(), // destNodeID - midiChannelIndex); // destNodeChannelIndex + std::cout << " Connecting " << source->getName() << + " event channel to " << + dest->getName() << std::endl; + + // connect event channel + addConnection(source->getNodeId(), // sourceNodeID + midiChannelIndex, // sourceNodeChannelIndex + dest->getNodeId(), // destNodeID + midiChannelIndex); // destNodeChannelIndex } @@ -279,7 +282,7 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect { dest = splitters.getFirst(); // dest is now the splitter splitters.remove(0); // take it out of the - dest->switchDest(); // switch to the other destination + dest->switchIO(); // switch to the other destination dest->wasConnected = true; // don't want to re-add splitter source = dest->getSourceNode(); // splitter is now source } @@ -288,15 +291,6 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect } // end "tabs" for loop } // end method -// int ProcessorGraph::getNextFreeAudioChannel() -// { -// return totalAudioConnections++; -// } - -// int ProcessorGraph::getNextFreeRecordChannel() -// { -// return totalRecordConnections++; -// } GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& description) { @@ -310,7 +304,8 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip if (processorType.equalsIgnoreCase("Sources")) { - if (subProcessorType.equalsIgnoreCase("Intan Demo Board")) { + if (subProcessorType.equalsIgnoreCase("Intan Demo Board") || + subProcessorType.equalsIgnoreCase("File Reader")) { // only one Intan Demo Board at a time, please if (!processorWithSameNameExists(subProcessorType)) { @@ -329,7 +324,7 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip } - sendActionMessage("New source node created."); + //sendActionMessage("New source node created."); } else if (processorType.equalsIgnoreCase("Filters")) { @@ -347,7 +342,7 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip processor = new SpikeDetector(); } - sendActionMessage("New filter node created."); + //sendActionMessage("New filter node created."); } else if (processorType.equalsIgnoreCase("Utilities")) { @@ -356,14 +351,14 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip std::cout << "Creating a new splitter." << std::endl; processor = new Splitter(); - sendActionMessage("New splitter created."); + // sendActionMessage("New splitter created."); } else if (subProcessorType.equalsIgnoreCase("Merger")) { std::cout << "Creating a new merger." << std::endl; processor = new Merger(); - sendActionMessage("New merger created."); + // sendActionMessage("New merger created."); } @@ -376,12 +371,17 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip // std::cout << "Graph data viewport: " << UI->getDataViewport() << std::endl; // processor->setDataViewport(getDataViewport()); //processor->setUIComponent(UI); - } else if (subProcessorType.equalsIgnoreCase("WiFi Output")) { + } + else if (subProcessorType.equalsIgnoreCase("Spike Viewer")) { + std::cout << "Creating an SpikeDisplayNode." << std::endl; + processor = new SpikeDisplayNode(); + } + else if (subProcessorType.equalsIgnoreCase("WiFi Output")) { std::cout << "Creating a WiFi node." << std::endl; processor = new WiFiOutput(); } - sendActionMessage("New sink created."); + //sendActionMessage("New sink created."); } return processor; @@ -403,6 +403,7 @@ bool ProcessorGraph::processorWithSameNameExists(const String& name) } + void ProcessorGraph::removeProcessor(GenericProcessor* processor) { std::cout << "Removing processor with ID " << processor->getNodeId() << std::endl; @@ -411,27 +412,6 @@ void ProcessorGraph::removeProcessor(GenericProcessor* processor) { } -// void ProcessorGraph::setUIComponent(UIComponent* ui) -// { -// UI = ui; -// } - -// void ProcessorGraph::setFilterViewport(FilterViewport* fv) -// { -// filterViewport = fv; -// } - -// void ProcessorGraph::setMessageCenter(MessageCenter* mc) -// { -// messageCenter = mc; -// } - -// void ProcessorGraph::setConfiguration(Configuration* c) -// { -// config = c; -// } - - bool ProcessorGraph::enableProcessors() { updateConnections(getEditorViewport()->requestSignalChain()); @@ -458,7 +438,7 @@ bool ProcessorGraph::enableProcessors() { if (!allClear) { std::cout << p->getName() << " said it's not OK." << std::endl; - sendActionMessage("Could not initialize acquisition."); + // sendActionMessage("Could not initialize acquisition."); getUIComponent()->disableCallbacks(); return false; @@ -480,7 +460,7 @@ bool ProcessorGraph::enableProcessors() { getEditorViewport()->signalChainCanBeEdited(false); - sendActionMessage("Acquisition started."); +// sendActionMessage("Acquisition started."); return true; } @@ -501,7 +481,7 @@ bool ProcessorGraph::disableProcessors() { allClear = p->disable(); if (!allClear) { - sendActionMessage("Could not stop acquisition."); + // sendActionMessage("Could not stop acquisition."); return false; } } @@ -509,7 +489,7 @@ bool ProcessorGraph::disableProcessors() { getEditorViewport()->signalChainCanBeEdited(true); - sendActionMessage("Acquisition ended."); +// sendActionMessage("Acquisition ended."); return true; } diff --git a/Source/Processors/ProcessorGraph.h b/Source/Processors/ProcessorGraph.h index 279ae740665397680f3415ed47fc706a67241577..914a574e884c637e0ad27a4757ae91ecc35bdc5f 100644 --- a/Source/Processors/ProcessorGraph.h +++ b/Source/Processors/ProcessorGraph.h @@ -45,13 +45,8 @@ class GenericProcessor; class RecordNode; -class SignalChainTabButton; class AudioNode; -//class SourceNode; -//class EditorViewport; -//class UIComponent; -//class Configuration; -//class MessageCenter; +class SignalChainTabButton; class ProcessorGraph : public AudioProcessorGraph, public AccessClass @@ -71,11 +66,6 @@ public: RecordNode* getRecordNode(); AudioNode* getAudioNode(); - //void setUIComponent(UIComponent* ui); - //void setFilterViewport(FilterViewport *fv); - //void setMessageCenter(MessageCenter* mc); - //void setConfiguration(Configuration* config); - void updateConnections(Array<SignalChainTabButton*, CriticalSection>); bool processorWithSameNameExists(const String& name); @@ -83,31 +73,21 @@ public: void saveState(); void loadState(); - //int getNextFreeAudioChannel(); - //int getNextFreeRecordChannel(); - private: int currentNodeId; - Array<int> source_node_IDs; - - const int RECORD_NODE_ID; - const int AUDIO_NODE_ID; - const int OUTPUT_NODE_ID; - const int RESAMPLING_NODE_ID; + enum nodeIds + { + RECORD_NODE_ID = 900, + AUDIO_NODE_ID = 901, + OUTPUT_NODE_ID = 902, + RESAMPLING_NODE_ID = 903 + }; void createDefaultNodes(); void clearConnections(); - //UIComponent* UI; - //FilterViewport* filterViewport; - ///Configuration* config; - //MessageCenter* messageCenter; - - //int totalAudioConnections; - //int totalRecordConnections; - }; diff --git a/Source/Processors/RecordNode.cpp b/Source/Processors/RecordNode.cpp index 25d01f1ef9b124b2b3e250923e7885445b77041a..eb4d13d03ff4549f70fd5cfda9091cfb221bc607 100644 --- a/Source/Processors/RecordNode.cpp +++ b/Source/Processors/RecordNode.cpp @@ -22,17 +22,16 @@ */ #include "RecordNode.h" +#include "ProcessorGraph.h" RecordNode::RecordNode() - : GenericProcessor("Record Node"), isRecording(false) + : GenericProcessor("Record Node"), isRecording(false), isProcessing(false) { - // need to update this: - setPlayConfigDetails(64,0,44100.0,128); + dataFolder = "./Data"; + + continuousDataBuffer = new int16[10000]; - //utputFile = File("./data"); // create output file - //outputStream = 0; - } @@ -40,20 +39,173 @@ RecordNode::~RecordNode() { } +void RecordNode::setChannel(int id, int chan) +{ + + std::cout << "Record node setting channel." << std::endl; + + for (int i = 0; i < continuousChannels.size(); i++) + { + + if (continuousChannels[i].nodeId == id && + continuousChannels[i].chan == chan) + { + std::cout << "Found channel " << i << std::endl; + setCurrentChannel(i); + break; + } + + } +} + +void RecordNode::resetConnections() +{ + //std::cout << "Resetting connections" << std::endl; + nextAvailableChannel = 0; + wasConnected = false; + + continuousChannels.clear(); + eventChannels.clear(); +} + + +void RecordNode::addInputChannel(GenericProcessor* sourceNode, int chan) +{ + + if (chan != getProcessorGraph()->midiChannelIndex) + { + Channel newChannel; + + std::cout << "Record node adding channel." << std::endl; + + newChannel.nodeId = sourceNode->getNodeId(); + newChannel.chan = chan; + newChannel.name = sourceNode->getOutputChannelName(chan); + newChannel.isRecording = sourceNode->recordStatus(chan); + + String filename = dataFolder; + filename += "/"; + filename += newChannel.nodeId; + filename += "_"; + filename += newChannel.name; + filename += ".continuous"; + + newChannel.filename = filename; + newChannel.file = 0; + + if (newChannel.isRecording) + std::cout << " This channel will be recorded." << std::endl; + else + std::cout << " This channel will NOT be recorded." << std::endl; + + std::cout << "adding channel " << getNextChannel(false) << std::endl; + + std::pair<int, Channel> newPair (getNextChannel(false), newChannel); + + continuousChannels.insert(newPair); + + setPlayConfigDetails(getNextChannel(false)+1,0,44100.0,128); + + } else { + + + std::map<int, Channel> eventChans; + + int ID = sourceNode->getNodeId(); + + for (int n = 0; n < sourceNode->settings.eventChannelIds.size(); n++) + { + + Channel newChannel; + + newChannel.nodeId = ID; + newChannel.chan = sourceNode->settings.eventChannelIds[n]; + newChannel.name = sourceNode->settings.eventChannelNames[n]; + newChannel.isRecording = true; + newChannel.file = 0; + + std::pair<int, Channel> newPair (newChannel.chan, newChannel); + + eventChans.insert(newPair); + + } + + std::pair<int, std::map<int, Channel> > newPair (ID, eventChans); + + eventChannels.insert(newPair); + + } + +} + void RecordNode::setParameter (int parameterIndex, float newValue) { if (parameterIndex == 1) { + isRecording = true; - } else { + std::cout << "START RECORDING." << std::endl; + + // create / open necessary files + for (int i = 0; i < continuousChannels.size(); i++) + { + if (continuousChannels[i].isRecording) + { + std::cout << "OPENING FILE: " << continuousChannels[i].filename << std::endl; + continuousChannels[i].file = fopen(continuousChannels[i].filename.toUTF8(), "a"); + } + } + + + } else if (parameterIndex == 0) { + + isRecording = false; + std::cout << "STOP RECORDING." << std::endl; + + // close necessary files + for (int i = 0; i < continuousChannels.size(); i++) + { + if (continuousChannels[i].isRecording) + { + std::cout << "CLOSING FILE: " << continuousChannels[i].filename << std::endl; + fclose(continuousChannels[i].file); + } + } + + // close necessary files + } else if (parameterIndex == 2) { + + if (isProcessing) { + + std::cout << "Toggling channel " << currentChannel << std::endl; + + if (newValue == 0.0f) { + continuousChannels[currentChannel].isRecording = false; + + if (isRecording) { + std::cout << "CLOSING FILE: " << continuousChannels[currentChannel].filename << std::endl; + fclose(continuousChannels[currentChannel].file); + } + + } + else { + continuousChannels[currentChannel].isRecording = true; + + if (isRecording) { + std::cout << "OPENING FILE: " << continuousChannels[currentChannel].filename << std::endl; + continuousChannels[currentChannel].file = + fopen(continuousChannels[currentChannel].filename.toUTF8(), "a"); + } + } + } } } bool RecordNode::enable() { - //outputStream = outputFile.createOutputStream(); + isProcessing = true; return true; } @@ -61,19 +213,52 @@ bool RecordNode::enable() bool RecordNode::disable() { - // if (outputStream != 0) { - // outputStream->flush(); + // close files if necessary + setParameter(0, 10.0f); - // delete(outputStream); - // outputStream = 0; - // } + isProcessing = false; return true; } float RecordNode::getFreeSpace() { - return (1.0f-float(outputFile.getBytesFreeOnVolume())/float(outputFile.getVolumeTotalSize())); + // this needs to be updated: + + return 0.5; + //return (1.0f-float(outputFile.getBytesFreeOnVolume())/float(outputFile.getVolumeTotalSize())); +} + +void RecordNode::writeContinuousBuffer(float* data, int nSamples, int channel) +{ + + // find file and write samples to disk + + AudioDataConverters::convertFloatToInt16BE(data, continuousDataBuffer, nSamples); + + //int16 samps = nSamples; + + fwrite(×tamp, // ptr + 8, // size of each element + 1, // count + continuousChannels[channel].file); // ptr to FILE object + + fwrite(&nSamples, // ptr + sizeof(nSamples), // size of each element + 1, // count + continuousChannels[channel].file); // ptr to FILE object + + int n = fwrite(continuousDataBuffer, // ptr + 2, // size of each element + nSamples, // count + continuousChannels[channel].file); // ptr to FILE object + // n must equal "count", otherwise there was an error +} + +void RecordNode::writeEventBuffer(MidiMessage& event, int node, int channel) +{ + // find file and write samples to disk + } void RecordNode::process(AudioSampleBuffer &buffer, @@ -84,17 +269,32 @@ void RecordNode::process(AudioSampleBuffer &buffer, //std::cout << "Record node processing block." << std::endl; //std::cout << "Num channels: " << buffer.getNumChannels() << std::endl; + timestamp = timer.getHighResolutionTicks(); + if (isRecording) { - //int nSamps = getNumSamples(midiMessages); + buffer.applyGain(0, nSamples, 0.1); + + // cycle through events -- extract the samples per channel + + + // cycle through buffer channels + for (int i = 0; i < buffer.getNumChannels(); i++) + { + + if (continuousChannels[i].isRecording) + { + // write buffer to disk! + writeContinuousBuffer(buffer.getSampleData(i), + nSamples, + i); + + //std::cout << "Record channel " << i << std::endl; + } + - for (int n = 0; n < nSamples; n++) { - - float* sample = buffer.getSampleData(1,n); - outputStream->writeFloat(*sample); - //AudioDataConverters::convertFloatToInt16BE(&sample) - //); } + } } diff --git a/Source/Processors/RecordNode.h b/Source/Processors/RecordNode.h index f4c9b54b45f4b8c6d18134047c726790b2676eb5..c129f6eb6c5b6d502d0ee8810b35e3c98d877e61 100644 --- a/Source/Processors/RecordNode.h +++ b/Source/Processors/RecordNode.h @@ -27,6 +27,7 @@ #include "../../JuceLibraryCode/JuceHeader.h" #include <stdio.h> +#include <map> #include "GenericProcessor.h" @@ -51,21 +52,51 @@ public: RecordNode(); ~RecordNode(); - void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples); + void process(AudioSampleBuffer &buffer, MidiBuffer &eventBuffer, int& nSamples); void setParameter (int parameterIndex, float newValue); + void addInputChannel(GenericProcessor* sourceNode, int chan); + bool enable(); bool disable(); float getFreeSpace(); + + void setChannel(int id, int chan); + + void resetConnections(); private: - - File outputFile; + + File headerFile; FileOutputStream* outputStream; - bool isRecording; + bool isRecording, isProcessing; + + String dataFolder; + + int16* continuousDataBuffer; + + int64 timestamp; + + Time timer; + + struct Channel + { + int nodeId; + int chan; + String name; + bool isRecording; + String filename; + FILE* file; + }; + + std::map<int, Channel> continuousChannels; + std::map<int, std::map<int,Channel> > eventChannels; + + void writeContinuousBuffer(float* data, int nSamples, int channel); + void writeEventBuffer(MidiMessage& event, int node, int channel); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RecordNode); diff --git a/Source/Processors/ResamplingNode.cpp b/Source/Processors/ResamplingNode.cpp index 1c17cdd5ce37359d78375eabd6e98efd1313c98c..9e66626244f52a6e67ebf88ee831c029dbc7eacc 100644 --- a/Source/Processors/ResamplingNode.cpp +++ b/Source/Processors/ResamplingNode.cpp @@ -33,11 +33,11 @@ ResamplingNode::ResamplingNode(bool destBufferType) { - setNumInputs(2); - setNumOutputs(2); + settings.numInputs = 2; + settings.numOutputs = 2; - setPlayConfigDetails(2, // number of inputs - 2, // number of outputs + setPlayConfigDetails(getNumInputs(), // number of inputs + getNumOutputs(), // number of outputs 44100.0, // sampleRate 128); // blockSize diff --git a/Source/Processors/SignalGenerator.cpp b/Source/Processors/SignalGenerator.cpp index 08093b35b4b8e70368bfb8d027252c8b3069240e..35b192f4566c04c81f93b3a0800477ffaaf44c90 100644 --- a/Source/Processors/SignalGenerator.cpp +++ b/Source/Processors/SignalGenerator.cpp @@ -23,69 +23,56 @@ #include "SignalGenerator.h" -//#include "SourceNodeEditor.h" #include <stdio.h> +#include <math.h> SignalGenerator::SignalGenerator() : GenericProcessor("Signal Generator"), defaultFrequency(10.0), - defaultAmplitude (0.02f) + defaultAmplitude (0.02f), + nOut(1) { - setNumOutputs(10); - setNumInputs(0); + // const String n = "Test"; + Parameter p = Parameter("Bill",true); - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); + p.setValue(0.0f, 0); + bool a = p[0]; + parameters.add(p); -} -SignalGenerator::~SignalGenerator() -{ - //config->removeDataSource(this); } -// void SignalGenerator::setConfiguration(Configuration* cf) -// { -// config = cf; - -// DataSource* d = new DataSource(this, config); +SignalGenerator::~SignalGenerator() +{ -// // add a new data source to this configuration -// config->addDataSource(d); +} -// } AudioProcessorEditor* SignalGenerator::createEditor( ) { - SignalGeneratorEditor* ed = new SignalGeneratorEditor(this); - setEditor(ed); - - std::cout << "Creating editor." << std::endl; - //filterEditor = new FilterEditor(this); - return ed; + editor = new SignalGeneratorEditor(this); + return editor; } -void SignalGenerator::updateParameters() +void SignalGenerator::updateSettings() { - std::cout << "Signal generator updating parameters" << std::endl; - - frequencies.clear(); - amplitudes.clear(); - currentPhase.clear(); - phasePerSample.clear(); + //std::cout << "Signal generator updating parameters" << std::endl; - for (int n = 0; n < getNumOutputs(); n++) + while (waveformType.size() < getNumOutputs()) { - frequencies.add(defaultFrequency*n); - amplitudes.add(defaultAmplitude); + waveformType.add(NOISE); + frequency.add(defaultFrequency); + amplitude.add(defaultAmplitude); + phase.add(0); + phasePerSample.add(double_Pi * 2.0 / (getSampleRate() / frequency.getLast())); currentPhase.add(0); - phasePerSample.add(double_Pi * 2.0 / (getSampleRate() / frequencies[n])); } } @@ -96,11 +83,17 @@ void SignalGenerator::setParameter (int parameterIndex, float newValue) if (currentChannel > -1) { if (parameterIndex == 0) { - amplitudes.set(currentChannel,newValue); - } else { - frequencies.set(currentChannel,newValue); - phasePerSample.set(currentChannel, double_Pi * 2.0 / (sampleRate / frequencies[currentChannel])); + amplitude.set(currentChannel,newValue); + } else if (parameterIndex == 1) { + frequency.set(currentChannel,newValue); + phasePerSample.set(currentChannel, double_Pi * 2.0 / (getSampleRate() / frequency[currentChannel])); + } else if (parameterIndex == 2) { + phase.set(currentChannel, newValue/360.0f * (double_Pi * 2.0)); + } else if (parameterIndex == 3) { + waveformType.set(currentChannel, (int) newValue); } + + //updateWaveform(currentChannel); } } @@ -109,9 +102,57 @@ void SignalGenerator::setParameter (int parameterIndex, float newValue) bool SignalGenerator::enable () { std::cout << "Signal generator received enable signal." << std::endl; + + // for (int n = 0; n < waveformType.size(); n++) + // { + // updateWaveform(n); + + // } + return true; } +// void SignalGenerator::updateWaveform(int n) +// { + + // Array<float> cycleData; + + // int cycleLength = int(getSampleRate() / frequency[n]); + // float phasePerSample = double_Pi * 2.0 / (getSampleRate() / frequency[n]); + + // cycleData.ensureStorageAllocated(cycleLength); + + // for (int i = 0; i < cycleLength; i++) + // { + // switch (waveformType[n]) + // { + // case SINE: + // cycleData.add(amplitude[n] * std::sin(i*phasePerSample + phase[n])); + // break; + // case SQUARE: + // cycleData.add(amplitude[n] * copysign(1,std::sin(i*phasePerSample + phase[n]))); + // break; + // case TRIANGLE: + // cycleData.add(0); + // break; + // case SAW: + // cycleData.add(0); + // break; + // case NOISE: + // cycleData.add(0); + // break; + // default: + // cycleData.set(i, 0); + // } + + // } + + // waveforms.set(n, cycleData); + + // currentSample.set(n,0); + +// } + bool SignalGenerator::disable() { std::cout << "Signal generator received disable signal." << std::endl; @@ -123,18 +164,111 @@ void SignalGenerator::process(AudioSampleBuffer &buffer, int& nSamps) { - //std::cout << buffer.getNumChannels() << std::endl; nSamps = buffer.getNumSamples(); - + for (int i = 0; i < nSamps; ++i) { for (int j = buffer.getNumChannels(); --j >= 0;) { + + float sample; + + switch (waveformType[j]) + { + case SINE: + sample = amplitude[j] * (float) std::sin (currentPhase[j] + phase[j]); + break; + case SQUARE: + sample = amplitude[j] * copysign(1,std::sin(currentPhase[j] + phase[j])); + break; + case TRIANGLE: + sample = amplitude[j] * ((currentPhase[j] + phase[j]) / double_Pi - 1) * + copysign(2,std::sin(currentPhase[j] + phase[j])); + break; + case SAW: + sample = amplitude[j] * ((currentPhase[j] + phase[j]) / double_Pi - 1); + break; + case NOISE: + sample = amplitude[j] * (float(rand()) / float(RAND_MAX)-0.5f); + break; + default: + sample = 0; + } - const float sample = amplitudes[j] * (float) std::sin (currentPhase[j]); currentPhase.set(j,currentPhase[j] + phasePerSample[j]); + if (currentPhase[j] > double_Pi*2) + currentPhase.set(j,0); + // dereference pointer to one of the buffer's samples *buffer.getSampleData (j, i) = sample; } } + + + + + // for (int chan = 0; chan < buffer.getNumChannels(); chan++) + // { + + // int dataSize = waveforms[chan].size(); + // int destSample = -dataSize; + // int lastSample = dataSize; + + // while (lastSample < nSamps) + // { + + // destSample += dataSize; + + // //std::cout << lastSample << " " << destSample << " " << currentSample[chan] << " " << dataSize << std::endl; + + // // buffer.copyFrom(chan, + // // destSample, + // // waveforms[chan].getRawDataPointer() + currentSample[chan], + // // dataSize - currentSample[chan]); + + // lastSample += dataSize; + + // currentSample.set(chan,0); + + // //std::cout << "DONE" << std::endl; + // } + + // //std::cout << lastSample << " " << destSample << " " << currentSample[chan] << " " << dataSize << std::endl; + + // if (destSample < 0) + // destSample = 0; + + // int samplesLeft = nSamps - destSample; + + // if (samplesLeft < dataSize - currentSample[chan]) + // { + // // buffer.copyFrom(chan, + // // destSample, + // // waveforms[chan].getRawDataPointer() + currentSample[chan], + // // samplesLeft); + + // currentSample.set(chan, currentSample[chan] + samplesLeft); + + // } else { + + // int samps = dataSize - currentSample[chan]; + + // // buffer.copyFrom(chan, + // // destSample, + // // waveforms[chan].getRawDataPointer() + currentSample[chan], + // // samps); + + // destSample += samps; + // samplesLeft -= samps; + + // // buffer.copyFrom(chan, + // // destSample, + // // waveforms[chan].getRawDataPointer(), + // // samplesLeft); + + // currentSample.set(chan, samplesLeft); + // } + + // } + } diff --git a/Source/Processors/SignalGenerator.h b/Source/Processors/SignalGenerator.h index abf1036edcff43ff4d3530e60b87b19c2d2d53ed..4ce5f106ad645b0201f7dad263ee8b5684348d9f 100644 --- a/Source/Processors/SignalGenerator.h +++ b/Source/Processors/SignalGenerator.h @@ -31,7 +31,7 @@ /** - Outputs 16 channels of sine wave data. + Outputs synthesized data of one of 5 different waveform types. @see GenericProcessor, SignalGeneratorEditor @@ -49,8 +49,6 @@ public: void setParameter (int parameterIndex, float newValue); - void setConfiguration(Configuration* cf); - float getSampleRate() {return 44100.0;} AudioProcessorEditor* createEditor(); @@ -61,18 +59,30 @@ public: bool isSource() {return true;} - void updateParameters(); + void updateSettings(); + + int getDefaultNumOutputs() {return nOut;} + + int nOut; private: double defaultFrequency; double defaultAmplitude; - Array<double> frequencies; - Array<double> amplitudes; - Array<double> currentPhase; - Array<double> phasePerSample; + //void updateWaveform(int chan); + + enum wvfrm + { + TRIANGLE, SINE, SQUARE, SAW, NOISE + }; + Array<int> waveformType; + Array<double> frequency; + Array<double> amplitude; + Array<double> phase; + Array<double> phasePerSample; + Array<double> currentPhase; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SignalGenerator); diff --git a/Source/Processors/SourceNode.cpp b/Source/Processors/SourceNode.cpp index fdbd4e1340fd2f8a95e361fd86ddf25dca346beb..e22db7a14f7720cc7b432ce45ef06bcb51293873 100644 --- a/Source/Processors/SourceNode.cpp +++ b/Source/Processors/SourceNode.cpp @@ -27,8 +27,8 @@ SourceNode::SourceNode(const String& name_) : GenericProcessor(name_), - dataThread(0), - sourceCheckInterval(750), wasDisabled(true) + dataThread(0), inputBuffer(0), + sourceCheckInterval(2000), wasDisabled(true) { if (getName().equalsIgnoreCase("Intan Demo Board")) { dataThread = new IntanThread(this); @@ -38,17 +38,6 @@ SourceNode::SourceNode(const String& name_) dataThread = new FileReaderThread(this); } - setNumInputs(0); - - if (dataThread != 0) { - setNumOutputs(dataThread->getNumChannels()); - inputBuffer = dataThread->getBufferAddress(); - } else { - setNumOutputs(10); - } - - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); - if (dataThread != 0) { if (!dataThread->foundInputSource()) @@ -59,17 +48,22 @@ SourceNode::SourceNode(const String& name_) enabledState(false); } - // check for input source every two seconds + // check for input source every few seconds startTimer(sourceCheckInterval); } SourceNode::~SourceNode() { - if (dataThread != 0) - deleteAndZero(dataThread); +} + +void SourceNode::updateSettings() +{ + if (inputBuffer == 0 && dataThread != 0) + { + inputBuffer = dataThread->getBufferAddress(); + } - //config->removeDataSource(this); } float SourceNode::getSampleRate() @@ -108,30 +102,6 @@ void SourceNode::enabledState(bool t) } -// void SourceNode::setConfiguration(Configuration* cf) -// { -// config = cf; - -// DataSource* d = new DataSource(this, config); - -// // // add tetrodes -- should really be doing this dynamically -// d->addTrode(4, "TT1"); -// d->addTrode(4, "TT2"); -// d->addTrode(4, "TT3"); -// d->addTrode(4, "TT4"); - -// for (int n = 0; n < d->numTetrodes(); n++) -// { -// std::cout << d->getTetrode(n)->getName(); -// } -// std::cout << std::endl; - -// // // add a new data source to this configuration -// config->addDataSource(d); - -// } - - void SourceNode::setParameter (int parameterIndex, float newValue) { //std::cout << "Got parameter change notification"; @@ -139,11 +109,8 @@ void SourceNode::setParameter (int parameterIndex, float newValue) AudioProcessorEditor* SourceNode::createEditor() { - SourceNodeEditor* ed = new SourceNodeEditor(this); - setEditor(ed); - - std::cout << "Creating editor." << std::endl; - return ed; + editor = new SourceNodeEditor(this); + return editor; } void SourceNode::timerCallback() @@ -154,16 +121,14 @@ void SourceNode::timerCallback() std::cout << "Input source found." << std::endl; //stopTimer(); // check for input source every two seconds enabledState(true); - GenericEditor* ed = (GenericEditor*) getEditor(); - //ed->enable(); + GenericEditor* ed = getEditor(); getEditorViewport()->makeEditorVisible(ed); } } else { if (isEnabled) { std::cout << "No input source found." << std::endl; enabledState(false); - GenericEditor* ed = (GenericEditor*) getEditor(); - //ed->disable(); + GenericEditor* ed = getEditor(); getEditorViewport()->makeEditorVisible(ed); } } @@ -194,29 +159,6 @@ bool SourceNode::enable() { stopTimer(); - - - // bool return_code = true; - - // if (getName().equalsIgnoreCase("Intan Demo Board")) { - - // dataThread = new IntanThread(); - // inputBuffer = dataThread->getBufferAddress(); - // return_code = dataThread->threadStarted(); - - // if (!return_code) - // deleteAndZero(dataThread); - - // } else if (getName().equalsIgnoreCase("Custom FPGA")) { - // dataThread = new FPGAThread(); - // inputBuffer = dataThread->getBufferAddress(); - // } else if (getName().equalsIgnoreCase("File Reader")) { - // dataThread = new FileReaderThread(); - // inputBuffer = dataThread->getBufferAddress(); - // } - - // return return_code; - } bool SourceNode::disable() { @@ -250,22 +192,14 @@ void SourceNode::acquisitionStopped() } -void SourceNode::process(AudioSampleBuffer &outputBuffer, - MidiBuffer &midiMessages, +void SourceNode::process(AudioSampleBuffer &buffer, + MidiBuffer &events, int& nSamples) { - - //std::cout << "Source node processing." << std::endl; - //std::cout << outputBuffer.getNumChannels() << " " << outputBuffer.getNumSamples() << std::endl; - - outputBuffer.clear(); - nSamples = inputBuffer->readAllFromBuffer(outputBuffer,outputBuffer.getNumSamples()); - // //setNumSamples(numRead); // write the total number of samples - // setNumSamples(midiMessages, numRead); - //std::cout << numRead << std::endl; - - //addMidiEvent(midiMessages,10, 10); + buffer.clear(); + nSamples = inputBuffer->readAllFromBuffer(buffer,buffer.getNumSamples()); + } diff --git a/Source/Processors/SourceNode.h b/Source/Processors/SourceNode.h index fd6664411f6dadfe73b6289313d229a58fe4ae44..03a6ef5ab15b90b32e34480e105751463f1a3004 100644 --- a/Source/Processors/SourceNode.h +++ b/Source/Processors/SourceNode.h @@ -53,22 +53,15 @@ public: ~SourceNode(); void enabledState(bool t); - - //void setName(const String name_); void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples); void setParameter (int parameterIndex, float newValue); - void setConfiguration(Configuration* cf); - float getSampleRate(); float getDefaultSampleRate(); int getDefaultNumOutputs(); - // void setSourceNode(GenericProcessor* sn); - // void setDestNode(GenericProcessor* dn); - AudioProcessorEditor* createEditor(); bool hasEditor() const {return true;} @@ -87,12 +80,13 @@ private: bool wasDisabled; - //const String name; void timerCallback(); - DataThread* dataThread; + ScopedPointer<DataThread> dataThread; DataBuffer* inputBuffer; + void updateSettings(); + int* numSamplesInThisBuffer; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SourceNode); diff --git a/Source/Processors/SpikeDetector.cpp b/Source/Processors/SpikeDetector.cpp index ee47256cdad0bfe40a3b4b19134814eeb0ed6303..ff8dcef3bc3f69db7bbc76cdf3108a688901e741 100644 --- a/Source/Processors/SpikeDetector.cpp +++ b/Source/Processors/SpikeDetector.cpp @@ -25,163 +25,393 @@ #include "SpikeDetector.h" SpikeDetector::SpikeDetector() - : GenericProcessor("Spike Detector"), - sampleRate (40000.0), threshold(5000.0), prePeakMs(0.2), postPeakMs(0.6), - accumulator(0) + : GenericProcessor("Spike Detector"), overflowBufferSize(100), + overflowBuffer(2,100), dataBuffer(overflowBuffer) { - spikeBuffer = new MidiBuffer(); + electrodeTypes.add("hentrode"); + electrodeTypes.add("duotrode"); + electrodeTypes.add("triode"); + electrodeTypes.add("tetrode"); + electrodeTypes.add("pentrode"); + electrodeTypes.add("hextrode"); + electrodeTypes.add("heptrode"); + electrodeTypes.add("octrode"); + electrodeTypes.add("enneatrode"); + electrodeTypes.add("decatrode"); + electrodeTypes.add("hendecatrode"); + electrodeTypes.add("dodecatrode"); + electrodeTypes.add("triskaidecatrode"); + electrodeTypes.add("tetrakaidecatrode"); + electrodeTypes.add("pentakaidecatrode"); + electrodeTypes.add("hexadecatrode"); + electrodeTypes.add("heptakaidecatrode"); + electrodeTypes.add("octakaidecatrode"); + electrodeTypes.add("enneakaidecatrode"); + electrodeTypes.add("icosatrode"); + + for (int i = 0; i < 21; i++) + { + electrodeCounter.add(0); + } } SpikeDetector::~SpikeDetector() { - deleteAndZero(spikeBuffer); + } AudioProcessorEditor* SpikeDetector::createEditor() { - - SpikeDetectorEditor* editor = new SpikeDetectorEditor(this); - - std::cout << "Creating editor." << std::endl; - - setEditor(editor); - + editor = new SpikeDetectorEditor(this); return editor; } -void SpikeDetector::setParameter (int parameterIndex, float newValue) +void SpikeDetector::updateSettings() { - //std::cout << "Message received." << std::endl; - if (parameterIndex == 0) { - for (int n = 0; n < getNumOutputs(); n++) - { - thresh.set(n,newValue); - } - } -} + overflowBuffer.setSize(getNumInputs(),overflowBufferSize); +} -bool SpikeDetector::enable() +bool SpikeDetector::addElectrode(int nChans) { - //std::cout << "SpikeDetector node preparing." << std::endl; - prePeakSamples = int((prePeakMs / 1000.0f) / (1/getSampleRate())); - postPeakSamples = int((postPeakMs / 1000.0f) / (1/getSampleRate())); + int firstChan; + + int currentVal = electrodeCounter[nChans]; + electrodeCounter.set(nChans,++currentVal); - thresh.ensureStorageAllocated(getNumOutputs()); - channels.ensureStorageAllocated(getNumOutputs()); - nChans.ensureStorageAllocated(getNumOutputs()); - isActive.ensureStorageAllocated(getNumOutputs()); - lastSpike.ensureStorageAllocated(getNumOutputs()); + String electrodeName = electrodeTypes[nChans-1]; + String newName = electrodeName.substring(0,1); + newName = newName.toUpperCase(); + electrodeName = electrodeName.substring(1,electrodeName.length()); + newName += electrodeName; + newName += " "; + newName += electrodeCounter[nChans]; - for (int n = 0; n < getNumOutputs(); n++) + if (electrodes.size() == 0) { - isActive.set(n,false); - lastSpike.set(n,-40); + firstChan = 0; + } else { + Electrode* e = electrodes.getLast(); + firstChan = *(e->channels+(e->numChannels-1))+1; } - // check configuration - for (int ds = 0; ds < getConfiguration()->numDataSources(); ds++) + Electrode* newElectrode = new Electrode(); + + newElectrode->name = newName; + newElectrode->numChannels = nChans; + newElectrode->prePeakSamples = 8; + newElectrode->postPeakSamples = 32; + newElectrode->thresholds = new double[nChans]; + newElectrode->isActive = new bool[nChans]; + newElectrode->channels = new int[nChans]; + + for (int i = 0; i < nChans; i++) { - for (int tt = 0; tt < getConfiguration()->getSource(ds)->numTetrodes(); tt++) - { + *(newElectrode->channels+i) = firstChan+i; + *(newElectrode->thresholds+i) = getDefaultThreshold(); + *(newElectrode->isActive+i) = true; + } - Trode* t = getConfiguration()->getSource(ds)->getTetrode(tt); + resetElectrode(newElectrode); - for (int ch = 0; ch < t->numChannels(); ch++) - { - thresh.set(t->getChannel(ch),t->getThreshold(ch)); - channels.set(t->getChannel(ch),t->getRawDataPointer()); - nChans.set(t->getChannel(ch),t->numChannels()); - isActive.set(t->getChannel(ch),t->getState(ch)); - } - } + electrodes.add(newElectrode); + +} + +float SpikeDetector::getDefaultThreshold() +{ + return 0.14; +} + +StringArray SpikeDetector::getElectrodeNames() +{ + StringArray names; + + for (int i = 0; i < electrodes.size(); i++) + { + names.add(electrodes[i]->name); } + return names; +} + +void SpikeDetector::resetElectrode(Electrode* e) +{ + e->lastBufferIndex = 0; +} + +bool SpikeDetector::removeElectrode(int index) +{ + + // std::cout << "Spike detector removing electrode" << std::endl; + + if (index > electrodes.size() || index < 0) + return false; + + electrodes.remove(index); return true; +} + +bool SpikeDetector::setName(int index, String newName) +{ + electrodes[index-1]->name = newName; +} + +bool SpikeDetector::setChannel(int electrodeIndex, int channelNum, int newChannel) +{ + *(electrodes[electrodeIndex]->channels+channelNum) = newChannel; +} +int SpikeDetector::getNumChannels(int index) +{ + return electrodes[index]->numChannels; +} + +int SpikeDetector::getChannel(int index, int i) +{ + return *(electrodes[index]->channels+i); +} + +void SpikeDetector::setParameter (int parameterIndex, float newValue) +{ + //std::cout << "Message received." << std::endl; + // if (parameterIndex == 0) + // { + // thresh.set(currentChannel,newValue); + // } + +} + + +bool SpikeDetector::enable() +{ + + useOverflowBuffer = false; + return true; } bool SpikeDetector::disable() { - thresh.clear(); - channels.clear(); - nChans.clear(); - isActive.clear(); - lastSpike.clear(); + + for (int n = 0; n < electrodes.size(); n++) + { + resetElectrode(electrodes[n]); + } return true; } +void SpikeDetector::createSpikeEvent(int& peakIndex, + int& electrodeNumber, int& currentChannel, + MidiBuffer& eventBuffer) +{ + + int spikeLength = electrodes[electrodeNumber]->prePeakSamples + + + electrodes[electrodeNumber]->postPeakSamples; + + uint8 dataSize = spikeLength*2; + + uint8 data[dataSize]; + uint8* dataptr = data; + + // cycle through buffer + for (int sample = 0; sample < spikeLength; sample++) + { + uint16 sampleValue = uint16(getNextSample(currentChannel) + 32768); + + *dataptr++ = uint8(sampleValue >> 8); + *dataptr++ = uint8(sampleValue & 255); + + sampleIndex++; + + } + + addEvent(eventBuffer, + SPIKE, + peakIndex, + uint8(electrodeNumber), + uint8(currentChannel), + dataSize, + data); + + sampleIndex -= spikeLength; // reset sample index + +} + void SpikeDetector::process(AudioSampleBuffer &buffer, - MidiBuffer &midiMessages, + MidiBuffer &events, int& nSamples) { - int maxSamples = nSamples;//getNumSamples(midiMessages); - int spikeSize = 2 + prePeakSamples*2 + postPeakSamples*2; + // cycle through electrodes + Electrode* electrode; + dataBuffer = buffer; - spikeBuffer->clear(); + //std::cout << dataBuffer.getMagnitude(0,nSamples) << std::endl; - for (int sample = prePeakSamples + 1; sample < maxSamples - postPeakSamples - 1; sample++) + for (int i = 0; i < electrodes.size(); i++) { - for (int chan = 0; chan < getNumOutputs(); chan++) + + //std::cout << "ELECTRODE " << i << std::endl; + + electrode = electrodes[i]; + + // refresh buffer index for this electrode + sampleIndex = electrode->lastBufferIndex - 1; // subtract 1 to account for + // increment at start of getNextSample() + + // cycle through samples + while (samplesAvailable(nSamples)) { - if (isActive[chan] && lastSpike[chan]+spikeSize < sample) // channel is active + + sampleIndex++; + + + // cycle through channels + for (int chan = 0; chan < electrode->numChannels; chan++) { - if (*buffer.getSampleData(chan,sample) > thresh[chan]) + + // std::cout << " channel " << chan << std::endl; + + if (*(electrode->isActive+chan)) { - // if thresh cross is detected on one channel - // save a waveform on all of them - // std::cout << "Thresh cross on channel " << chan << ": " << thresh[chan] << std::endl; - // std::cout << " Capturing spikes on " << nChans[chan] << " channels." << std::endl; - for (int wire = 0; wire < nChans[chan]; wire++) + int currentChannel = *(electrode->channels+chan); + + if (getNextSample(currentChannel) > *(electrode->thresholds+chan)) // trigger spike { - int* firstChan = channels[chan]; - int channelNum = *(firstChan+wire); - //std::cout << " Found spike on channel " << channelNum << std::endl; + //std::cout << "Spike detected on electrode " << i << std::endl; + // find the peak + int peakIndex = sampleIndex; - uint8 data[spikeSize]; - data[0] = channelNum >> 8; // channel most-significant byte - data[1] = channelNum & 0xFF; // channel least-significant byte + while (getCurrentSample(currentChannel) < + getNextSample(currentChannel) && + sampleIndex < peakIndex + electrode->postPeakSamples) + { + sampleIndex++; + } - // not currently looking for peak, just centering on thresh cross - uint8* dataptr = data+2; + peakIndex = sampleIndex; + sampleIndex -= (electrode->prePeakSamples+1); - for (int s = -prePeakSamples; s < postPeakSamples; s++) { - - uint16 sampleValue = uint16(*buffer.getSampleData(channelNum, sample+s) + 32768); + // package spikes; + for (int currentChannel = 0; currentChannel < electrode->numChannels; currentChannel++) + { - *dataptr++ = uint8(sampleValue >> 8); - *dataptr++ = uint8(sampleValue & 255); + if (*(electrode->isActive+currentChannel)) + { + createSpikeEvent(peakIndex, // peak index + i, // electrodeNumber + currentChannel, // channel number + events); // event buffer + + + } // end if channel is active } - // broadcast spike - spikeBuffer->addEvent(data, // spike data - sizeof(data), // total bytes - sample); // sample index - - // keep track of last spike - lastSpike.set(channelNum, sample-prePeakSamples); - - } - } - } - } - } + // advance the sample index + sampleIndex = peakIndex + electrode->postPeakSamples; - // reset lastSpike at the end of each buffer - for (int n = 0; n < getNumOutputs(); n++) + break; // quit "for" loop + } // end spike trigger + + } // end if chanel is active + } // end cycle through channels + + } // end cycle through samples + + electrode->lastBufferIndex = sampleIndex - nSamples; // should be negative + + jassert(electrode->lastBufferIndex < 0); + + } // end cycle through electrodes + + // copy end of this buffer into the overflow buffer + + //std::cout << "Copying buffer" << std::endl; + // std::cout << "nSamples: " << nSamples; + //std::cout << "overflowBufferSize:" << overflowBufferSize; + + //if (nSamples > overflowBufferSize) { + + for (int i = 0; i < overflowBuffer.getNumChannels(); i++) { - lastSpike.set(n,-40); + overflowBuffer.copyFrom(i, 0, + buffer, i, + nSamples-overflowBufferSize, + overflowBufferSize); } + useOverflowBuffer = true; + //} else { + // useOverflowBuffer = false; + // } + +} + +float SpikeDetector::getNextSample(int& chan) +{ + + + + //if (useOverflowBuffer) + //{ + if (sampleIndex < 0) + { + // std::cout << " sample index " << sampleIndex << "from overflowBuffer" << std::endl; + return *overflowBuffer.getSampleData(chan, overflowBufferSize + sampleIndex); + } else { + // useOverflowBuffer = false; + // std::cout << " sample index " << sampleIndex << "from regular buffer" << std::endl; + return *dataBuffer.getSampleData(chan, sampleIndex); + } + //} else { + // std::cout << " sample index " << sampleIndex << "from regular buffer" << std::endl; + // return *dataBuffer.getSampleData(chan, sampleIndex); + //} + +} + +float SpikeDetector::getCurrentSample(int& chan) +{ + + // if (useOverflowBuffer) + // { + // return *overflowBuffer.getSampleData(chan, overflowBufferSize + sampleIndex - 1); + // } else { + // return *dataBuffer.getSampleData(chan, sampleIndex - 1); + // } + if (sampleIndex < 1) + { + //std::cout << " sample index " << sampleIndex << "from overflowBuffer" << std::endl; + return *overflowBuffer.getSampleData(chan, overflowBufferSize + sampleIndex - 1); + } else { + // useOverflowBuffer = false; + // std::cout << " sample index " << sampleIndex << "from regular buffer" << std::endl; + return *dataBuffer.getSampleData(chan, sampleIndex - 1); + } + //} else { } + + +bool SpikeDetector::samplesAvailable(int& nSamples) +{ + + if (sampleIndex > nSamples - overflowBufferSize/2) + { + return false; + } else { + return true; + } + +} + + diff --git a/Source/Processors/SpikeDetector.h b/Source/Processors/SpikeDetector.h index 8d0a1059e24a74ec24d3edd90b56b5a5c7d42073..065dbca51454d6d01cb06f7e048e462a3c41a68b 100644 --- a/Source/Processors/SpikeDetector.h +++ b/Source/Processors/SpikeDetector.h @@ -25,13 +25,13 @@ #define __SPIKEDETECTOR_H_3F920F95__ #include "../../JuceLibraryCode/JuceHeader.h" + #include "GenericProcessor.h" #include "Editors/SpikeDetectorEditor.h" -#include "../UI/Configuration.h" /** - --UNDER CONSTRUCTION-- + == UNDER CONSTRUCTION == Detects spikes in a continuous signal and outputs events containing the spike data. @@ -40,7 +40,6 @@ */ class SpikeDetectorEditor; -class FilterViewport; class SpikeDetector : public GenericProcessor @@ -50,33 +49,70 @@ public: SpikeDetector(); ~SpikeDetector(); - void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples); + void process(AudioSampleBuffer &buffer, MidiBuffer &events, int& nSamples); void setParameter (int parameterIndex, float newValue); + void updateSettings(); + bool enable(); bool disable(); - MidiBuffer* getEventBuffer() {return spikeBuffer;} - AudioProcessorEditor* createEditor(); - bool hasEditor() const {return true;} - + AudioSampleBuffer overflowBuffer; + AudioSampleBuffer& dataBuffer; + + bool addElectrode(int nChans); + bool removeElectrode(int index); + bool setChannel(int electrodeIndex, int channelNum, int newChannel); + bool setName(int index, String newName); + + int getNumChannels(int index); + int getChannel(int index, int chan); + + StringArray electrodeTypes; + + StringArray getElectrodeNames(); + private: - double sampleRate, threshold; - double prePeakMs, postPeakMs; - int prePeakSamples, postPeakSamples; - int accumulator; - Array<float> thresh; - Array<int*> channels; - Array<int> nChans; - Array<bool> isActive; - Array<int> lastSpike; + float getDefaultThreshold(); + + int overflowBufferSize; + + int sampleIndex; + //int lastBufferIndex; + + Array<int> electrodeCounter; + + float getNextSample(int& chan); + float getCurrentSample(int& chan); + bool samplesAvailable(int& nSamples); + + bool useOverflowBuffer; + + struct Electrode { + + String name; + + int numChannels; + int prePeakSamples, postPeakSamples; + int lastBufferIndex; + + int* channels; + double* thresholds; + bool* isActive; + + }; + + Array<Electrode*> electrodes; - MidiBuffer* spikeBuffer; + void createSpikeEvent(int& peakIndex, + int& electrodeNumber, + int& currentChannel, + MidiBuffer& eventBuffer); - //AudioData::ConverterInstance<AudioData::Float32, AudioData::Int16> converter; + void resetElectrode(Electrode*); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDetector); diff --git a/Source/Processors/SpikeDisplayNode.cpp b/Source/Processors/SpikeDisplayNode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..471a8267f2936acec06e724a30f3979e181be3ab --- /dev/null +++ b/Source/Processors/SpikeDisplayNode.cpp @@ -0,0 +1,119 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "SpikeDisplayNode.h" +#include <stdio.h> + + + +SpikeDisplayNode::SpikeDisplayNode() + : GenericProcessor("Spike Viewer"), + bufferSize(0), abstractFifo(100) + +{ +// displayBuffer = new AudioSampleBuffer(8, 100); + eventBuffer = new MidiBuffer(); +} + +SpikeDisplayNode::~SpikeDisplayNode() +{ + //deleteAndZero(displayBuffer); + //deleteAndZero(eventBuffer); +} + +AudioProcessorEditor* SpikeDisplayNode::createEditor() +{ + std::cout<<"SpikeDisplayNode Created!"<<std::endl; + + editor = new SpikeDisplayEditor(this); + return editor; + +} + +void SpikeDisplayNode::updateSettings() +{ + std::cout << "Setting num inputs on SpikeDisplayNode to " << getNumInputs() << std::endl; +} + + +bool SpikeDisplayNode::enable() +{ + std::cout<<"SpikeDisplayNode::enable()"<<std::endl; + SpikeDisplayEditor* editor = (SpikeDisplayEditor*) getEditor(); + editor->enable(); + return true; + +} + +bool SpikeDisplayNode::disable() +{ + std::cout<<"SpikeDisplayNode disabled!"<<std::endl; + SpikeDisplayEditor* editor = (SpikeDisplayEditor*) getEditor(); + editor->disable(); + return true; +} + +int SpikeDisplayNode::getNumberOfChannelsForInput(int i){ + std::cout<<"SpikeDisplayNode::getNumberOfChannelsForInput()"<<std::endl; + return 1; +} + + +void SpikeDisplayNode::setParameter (int param, float val) +{ + std::cout<<"Got Param:"<< param<< " with value:"<<val<<std::endl; +} + + + +void SpikeDisplayNode::process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples) +{ + //std::cout<<"SpikeDisplayNode::process"<<std::endl; + /* + uint64_t ts = 00000; + int noise = 10; + SpikeObject newSpike; + + generateSimulatedSpike(&newSpike, ts, noise); + + spikebuffer.push(newSpike); + bufferSize++; + */ +} + +bool SpikeDisplayNode::getNextSpike(SpikeObject *spike){ + std::cout<<"SpikeDisplayNode::getNextSpike()"<<std::endl; + /* + if (bufferSize<1 || spikebuffer.empty()) + return false; + else{ + SpikeObject s = spikebuffer.front(); + spikebuffer.pop(); + bufferSize--; + *spike = s; + return true; + } + */ + return false; + +} \ No newline at end of file diff --git a/Source/Processors/SpikeDisplayNode.h b/Source/Processors/SpikeDisplayNode.h new file mode 100644 index 0000000000000000000000000000000000000000..02092c5a032da33f8d7fa7bc4018464b71fa62ca --- /dev/null +++ b/Source/Processors/SpikeDisplayNode.h @@ -0,0 +1,95 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef SPIKEDISPLAYNODE_H_ +#define SPIKEDISPLAYNODE_H_ + +#include "../../JuceLibraryCode/JuceHeader.h" +#include "Editors/SpikeDisplayEditor.h" +#include "Editors/VisualizerEditor.h" +#include "GenericProcessor.h" +#include "Visualization/SpikeObject.h" + + + +#define SPIKE_CMD_CLEAR_ALL 10000 +#define SPIKE_CMD_CLEAR_SEL 10001 +#define SPIKE_CMD_PAN_AXES 10002 +#define SPIKE_CMD_ZOOM_AXES 10003 + + +/** + + Takes in MidiEvents and extracts SpikeObjects from the MidiEvent buffers. Those Events are then held in a queue until they are pulled by the spikeviewer + + @see GenericProcessor, SpikeDisplayEditor, SpikeDisplayCanvas + +*/ + + + +class DataViewport; + +class SpikeDisplayNode : public GenericProcessor +{ +public: + + SpikeDisplayNode(); + ~SpikeDisplayNode(); + + AudioProcessorEditor* createEditor(); + + bool isSink() {return true;} + + void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples); + + void setParameter(int, float); + + void updateSettings(); + + bool enable(); + bool disable(); + + int getNumberOfChannelsForInput(int i); + + bool getNextSpike(SpikeObject *spike); + +private: + + int numberOfSources; + AbstractFifo abstractFifo; + + ScopedPointer<AudioSampleBuffer> displayBuffer; + ScopedPointer<MidiBuffer> eventBuffer; + + //std::queue<SpikeObject> spikebuffer; + + int bufferSize; + //bool resizeBuffer(); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayNode); + +}; + + +#endif // SPIKEDISPLAYNODE_H_ diff --git a/Source/Processors/Utilities/Merger.cpp b/Source/Processors/Utilities/Merger.cpp index 2ac4ae8121e3bd6fc81f90d49e52db2caa24d265..fd6f69cc7f8b66f8c332005d0c20e71d15f1d490 100644 --- a/Source/Processors/Utilities/Merger.cpp +++ b/Source/Processors/Utilities/Merger.cpp @@ -30,10 +30,7 @@ Merger::Merger() : GenericProcessor("Merger"), sourceNodeA(0), sourceNodeB(0), activePath(0)//, tabA(-1), tabB(-1) { - setNumOutputs(0); - setNumInputs(0); - - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); + } Merger::~Merger() @@ -43,10 +40,10 @@ Merger::~Merger() AudioProcessorEditor* Merger::createEditor() { - MergerEditor* editor = new MergerEditor(this); - setEditor(editor); + editor = new MergerEditor(this); + //tEditor(editor); - std::cout << "Creating editor." << std::endl; + //std::cout << "Creating editor." << std::endl; return editor; } @@ -64,7 +61,7 @@ void Merger::setMergerSourceNode(GenericProcessor* sn) } } -void Merger::switchSource(int sourceNum) { +void Merger::switchIO(int sourceNum) { //std::cout << "Switching to source number " << sourceNum << std::endl; @@ -95,8 +92,11 @@ bool Merger::stillHasSource() } -void Merger::switchSource() +void Merger::switchIO() { + + std::cout << "Merger switching source." << std::endl; + if (activePath == 0) { activePath = 1; sourceNode = sourceNodeB; @@ -108,25 +108,55 @@ void Merger::switchSource() } -void Merger::setNumInputs(int n) +void Merger::addSettingsFromSourceNode(GenericProcessor* sn) +{ + + settings.numInputs += sn->getNumOutputs(); + settings.inputChannelNames.addArray(sn->settings.inputChannelNames); + settings.eventChannelIds.addArray(sn->settings.eventChannelIds); + settings.eventChannelNames.addArray(sn->settings.eventChannelNames); + settings.bitVolts.addArray(sn->settings.bitVolts); + + settings.originalSource = sn->settings.originalSource; + settings.sampleRate = sn->settings.sampleRate; + + settings.numOutputs = settings.numInputs; + settings.outputChannelNames = settings.inputChannelNames; + +} + +void Merger::updateSettings() { - numInputs = 0; + + // default is to get everything from sourceNodeA, + // but this might not be ideal + clearSettings(); if (sourceNodeA != 0) { std::cout << " Merger source A found." << std::endl; - numInputs += sourceNodeA->getNumOutputs(); + addSettingsFromSourceNode(sourceNodeA); } + if (sourceNodeB != 0) { std::cout << " Merger source B found." << std::endl; - numInputs += sourceNodeB->getNumOutputs(); + addSettingsFromSourceNode(sourceNodeB); + } + + if (sourceNodeA == 0 && sourceNodeB == 0) { + + settings.sampleRate = getDefaultSampleRate(); + settings.numOutputs = getDefaultNumOutputs(); + + for (int i = 0; i < getNumOutputs(); i++) + settings.bitVolts.add(getDefaultBitVolts()); + + generateDefaultChannelNames(settings.outputChannelNames); } std::cout << "Number of merger outputs: " << getNumInputs() << std::endl; - setNumOutputs(getNumInputs()); - } // void Merger::setNumOutputs(int /*outputs*/) diff --git a/Source/Processors/Utilities/Merger.h b/Source/Processors/Utilities/Merger.h index 66d4459bc188844581cabd3cb6175e1f724d5bea..7b416027915a4b5b5c0417520c013d737b6df8d9 100644 --- a/Source/Processors/Utilities/Merger.h +++ b/Source/Processors/Utilities/Merger.h @@ -51,11 +51,12 @@ public: bool isMerger() {return true;} - void switchSource(int); - void switchSource(); + void switchIO(int); + void switchIO(); void setMergerSourceNode(GenericProcessor* sn); - void setNumInputs(int); + void updateSettings(); + void addSettingsFromSourceNode(GenericProcessor* sn); bool stillHasSource(); diff --git a/Source/Processors/Utilities/Splitter.cpp b/Source/Processors/Utilities/Splitter.cpp index f259291f9e2a06bdbfb93a2128c95d806df1d577..fed00295d36a987e2b649c7f14b13063dec279e8 100644 --- a/Source/Processors/Utilities/Splitter.cpp +++ b/Source/Processors/Utilities/Splitter.cpp @@ -31,10 +31,6 @@ Splitter::Splitter() destNodeA(0), destNodeB(0), activePath(0) { - setNumOutputs(0); - setNumInputs(0); - - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); } Splitter::~Splitter() @@ -44,10 +40,10 @@ Splitter::~Splitter() AudioProcessorEditor* Splitter::createEditor() { - SplitterEditor* editor = new SplitterEditor(this); - setEditor(editor); + editor = new SplitterEditor(this); + //tEditor(editor); - std::cout << "Creating editor." << std::endl; + //std::cout << "Creating editor." << std::endl; return editor; } @@ -65,7 +61,7 @@ void Splitter::setSplitterDestNode(GenericProcessor* dn) } } -void Splitter::switchDest(int destNum) { +void Splitter::switchIO(int destNum) { std::cout << "Switching to dest number " << destNum << std::endl; @@ -81,12 +77,15 @@ void Splitter::switchDest(int destNum) { std::cout << "Dest node: " << getDestNode() << std::endl; } - getEditorViewport()->makeEditorVisible((GenericEditor*) getEditor()); + getEditorViewport()->makeEditorVisible(getEditor()); } -void Splitter::switchDest() +void Splitter::switchIO() { + + std::cout << "Splitter switching source." << std::endl; + if (activePath == 0) { activePath = 1; destNode = destNodeB; @@ -97,9 +96,3 @@ void Splitter::switchDest() } } - -void Splitter::setNumInputs(int n) -{ - numInputs = n; - setNumOutputs(getNumInputs()); -} \ No newline at end of file diff --git a/Source/Processors/Utilities/Splitter.h b/Source/Processors/Utilities/Splitter.h index 69581ba625c6fc5ee72ba6793032cce4dee4a8d9..ed775bdcf4ebe83ab5ed07ec52a80218f1479609 100644 --- a/Source/Processors/Utilities/Splitter.h +++ b/Source/Processors/Utilities/Splitter.h @@ -53,11 +53,10 @@ public: bool isSplitter() {return true;} - void switchDest(int); - void switchDest(); + void switchIO(int); + void switchIO(); void setSplitterDestNode(GenericProcessor* dn); - void setNumInputs(int); private: diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.cpp b/Source/Processors/Visualization/LfpDisplayCanvas.cpp index 809dbcc15317f1db104d7fa7f711653ed39dc75e..7e7a9251e8b33883698a0887ba87a4fd18a4e315 100644 --- a/Source/Processors/Visualization/LfpDisplayCanvas.cpp +++ b/Source/Processors/Visualization/LfpDisplayCanvas.cpp @@ -29,21 +29,21 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* n) : processor(n), timebase(1.0f), displayGain(5.0f), displayBufferIndex(0) { - //GenericProcessor* gp = (GenericProcessor*) editor->getProcessor(); - - nChans = processor->getNumInputs(); sampleRate = processor->getSampleRate(); std::cout << "Setting num inputs on LfpDisplayCanvas to " << nChans << std::endl; displayBuffer = processor->getDisplayBufferAddress(); displayBufferSize = displayBuffer->getNumSamples(); - std::cout << "Setting displayBufferSize on LfpDisplayCanvas to " << displayBufferSize << std::endl; + std::cout << "Setting displayBufferSize on LfpDisplayCanvas to " << displayBufferSize << std::endl; totalHeight = (plotHeight+yBuffer)*nChans + yBuffer; - screenBuffer = new AudioSampleBuffer(nChans, 10000); + if (nChans > 0) + screenBuffer = new AudioSampleBuffer(nChans, 10000); + else + screenBuffer = new AudioSampleBuffer(1, 10000); } @@ -86,22 +86,24 @@ void LfpDisplayCanvas::endAnimation() stopCallbacks(); } -void LfpDisplayCanvas::updateNumInputs(int n) +void LfpDisplayCanvas::update() { - std::cout << "Setting num inputs on LfpDisplayCanvas to " << n << std::endl; - nChans = n; - if (n < 200 && n > 0) + nChans = processor->getNumInputs(); + sampleRate = processor->getSampleRate(); + + std::cout << "Setting num inputs on LfpDisplayCanvas to " << nChans << std::endl; + if (nChans < 200 && nChans > 0) screenBuffer->setSize(nChans, 10000); //sampleRate = processor->getSampleRate(); -} -void LfpDisplayCanvas::updateSampleRate(float r) -{ - sampleRate = r; - //displayBufferSize = displayBuffer->getNumSamples(); - std::cout << "Display canvas updating sample rate to " << r << std::endl; + screenBuffer->clear(); + + repaint(); + + totalHeight = (plotHeight+yBuffer)*nChans + yBuffer; } + void LfpDisplayCanvas::setParameter(int param, float val) { if (param == 0) @@ -117,6 +119,8 @@ void LfpDisplayCanvas::refreshState() displayBufferIndex = processor->getDisplayBufferIndex(); screenBufferIndex = 0; + //resized(); + } void LfpDisplayCanvas::updateScreenBuffer() @@ -202,6 +206,10 @@ void LfpDisplayCanvas::updateScreenBuffer() } } +void LfpDisplayCanvas::canvasWasResized() +{ + //std::cout << "Resized!" << std::endl; +} void LfpDisplayCanvas::renderOpenGL() { @@ -343,7 +351,7 @@ int LfpDisplayCanvas::getTotalHeight() } -void LfpDisplayCanvas::mouseDown(const MouseEvent& e) +void LfpDisplayCanvas::mouseDownInCanvas(const MouseEvent& e) { Point<int> pos = e.getPosition(); @@ -358,7 +366,6 @@ void LfpDisplayCanvas::mouseDown(const MouseEvent& e) repaint(); } - mouseDownInCanvas(e); } // void LfpDisplayCanvas::mouseDrag(const MouseEvent& e) {mouseDragInCanvas(e);} diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.h b/Source/Processors/Visualization/LfpDisplayCanvas.h index e124911962481dc5cf347c995fb14440fabc24b3..a274076cc8ca571f31790f464faf74d649e8944f 100644 --- a/Source/Processors/Visualization/LfpDisplayCanvas.h +++ b/Source/Processors/Visualization/LfpDisplayCanvas.h @@ -23,15 +23,13 @@ #ifndef __LFPDISPLAYCANVAS_H_B711873A__ #define __LFPDISPLAYCANVAS_H_B711873A__ - #include "../../../JuceLibraryCode/JuceHeader.h" -#include "OpenGLCanvas.h" -#include "../../UI/Configuration.h" #include "../LfpDisplayNode.h" +#include "Visualizer.h" class LfpDisplayNode; -class LfpDisplayCanvas : public OpenGLCanvas +class LfpDisplayCanvas : public Visualizer { public: @@ -45,10 +43,11 @@ public: void refreshState(); - void updateNumInputs(int); - void updateSampleRate(float); + void update(); void setParameter(int, float); + void setParameter(int, int, int, float){} + private: @@ -57,7 +56,6 @@ private: float sampleRate; float timebase; float displayGain; - //float ratio; LfpDisplayNode* processor; AudioSampleBuffer* displayBuffer; @@ -73,8 +71,6 @@ private: bool checkBounds(int chan); - - void updateScreenBuffer(); int screenBufferIndex; int displayBufferIndex; @@ -85,8 +81,8 @@ private: int getTotalHeight(); - // void resized(); - void mouseDown(const MouseEvent& e); + void canvasWasResized(); + void mouseDownInCanvas(const MouseEvent& e); // void mouseDrag(const MouseEvent& e); // void mouseMove(const MouseEvent& e); // void mouseUp(const MouseEvent& e); diff --git a/Source/Processors/Visualization/OpenGLCanvas.cpp b/Source/Processors/Visualization/OpenGLCanvas.cpp index 4353220dc26d1c308db8c2df49c325aed032b9b9..a51104ccbb736f2ef4a92ee75e8dd2c2753b4880 100644 --- a/Source/Processors/Visualization/OpenGLCanvas.cpp +++ b/Source/Processors/Visualization/OpenGLCanvas.cpp @@ -28,7 +28,7 @@ OpenGLCanvas::OpenGLCanvas() : //OpenGLComponent(OpenGLComponent::OpenGLType::openGLDefault, true), scrollPix(0), scrollTime(0), scrollDiff(0), originalScrollPix(0), scrollBarWidth(15), PI(3.1415926), showScrollTrack(true), - animationIsActive(false), refreshMs(100) + animationIsActive(false), refreshMs(50) { loadFonts(); @@ -45,16 +45,29 @@ OpenGLCanvas::~OpenGLCanvas() void OpenGLCanvas::setUp2DCanvas() { glMatrixMode (GL_PROJECTION); + glLoadIdentity(); + glMatrixMode (GL_MODELVIEW); glLoadIdentity(); + glOrtho (0, 1, 1, 0, 0, 1); - glMatrixMode (GL_MODELVIEW); glEnable(GL_TEXTURE_2D); } void OpenGLCanvas::activateAntiAliasing() { + + // disable everything we don't need + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + glDisable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_STENCIL_TEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); @@ -65,6 +78,8 @@ void OpenGLCanvas::activateAntiAliasing() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glShadeModel(GL_FLAT); } @@ -195,6 +210,7 @@ void OpenGLCanvas::stopCallbacks() void OpenGLCanvas::drawScrollBars() { + float scrollBarY = float(getHeight())/float(getTotalHeight()); float timeSinceScroll = timer->getMillisecondCounter()-scrollTime; @@ -223,6 +239,7 @@ void OpenGLCanvas::drawScrollBars() } showScrollTrack = false; } + } void OpenGLCanvas::drawScrollBar(float y1, float y2, float alpha) @@ -334,7 +351,7 @@ void OpenGLCanvas::drawRoundedRect(float x, } -void OpenGLCanvas::mouseMoveInCanvas(const MouseEvent& e) +void OpenGLCanvas::mouseMove(const MouseEvent& e) { if (getTotalHeight() > getHeight()) { Point<int> pos = e.getPosition(); @@ -344,9 +361,11 @@ void OpenGLCanvas::mouseMoveInCanvas(const MouseEvent& e) showScrollTrack = true; showScrollBars(); } } + + mouseMoveInCanvas(e); } -void OpenGLCanvas::mouseDownInCanvas(const MouseEvent& e) +void OpenGLCanvas::mouseDown(const MouseEvent& e) { if (getTotalHeight() > getHeight()) { @@ -376,9 +395,11 @@ void OpenGLCanvas::mouseDownInCanvas(const MouseEvent& e) showScrollBars(); } } + + mouseDownInCanvas(e); } -void OpenGLCanvas::mouseDragInCanvas(const MouseEvent& e) +void OpenGLCanvas::mouseDrag(const MouseEvent& e) { if (getTotalHeight() > getHeight()) { @@ -415,54 +436,48 @@ void OpenGLCanvas::mouseDragInCanvas(const MouseEvent& e) } } } + + mouseDragInCanvas(e); } -void OpenGLCanvas::mouseUpInCanvas(const MouseEvent& e) +void OpenGLCanvas::mouseUp(const MouseEvent& e) { scrollDiff = 0; + + mouseUpInCanvas(e); } -void OpenGLCanvas::mouseWheelMoveInCanvas(const MouseEvent&e, +void OpenGLCanvas::mouseWheelMove(const MouseEvent&e, float wheelIncrementX, float wheelIncrementY) { if (getTotalHeight() > getHeight()) { - if (wheelIncrementY > 0) - { - if (scrollPix + getHeight() < getTotalHeight()) + + if (wheelIncrementY > 0) { - scrollPix += int(100.0f*wheelIncrementY); - if (scrollPix + getHeight() > getTotalHeight()) - scrollPix = getTotalHeight() - getHeight(); - } - } else if (wheelIncrementY < 0) - { - if (scrollPix > 0) + if (scrollPix + getHeight() < getTotalHeight()) + { + scrollPix += int(100.0f*wheelIncrementY); + if (scrollPix + getHeight() > getTotalHeight()) + scrollPix = getTotalHeight() - getHeight(); + } + } else if (wheelIncrementY < 0) { - scrollPix += int(100.0f*wheelIncrementY); - if (scrollPix < 0) - scrollPix = 0; + if (scrollPix > 0) + { + scrollPix += int(100.0f*wheelIncrementY); + if (scrollPix < 0) + scrollPix = 0; + } } - } - repaint(); + repaint(); - showScrollBars(); + showScrollBars(); } -} - -void OpenGLCanvas::canvasWasResized() -{ - //glClear(GL_COLOR_BUFFER_BIT); - - if (scrollPix + getHeight() > getTotalHeight() && getTotalHeight() > getHeight()) - scrollPix = getTotalHeight() - getHeight(); - else - scrollPix = 0; - - showScrollBars(); + mouseWheelMoveInCanvas(e, wheelIncrementX, wheelIncrementY); } @@ -472,18 +487,15 @@ void OpenGLCanvas::timerCallback() } - -void OpenGLCanvas::mouseDown(const MouseEvent& e) +void OpenGLCanvas::resized() { - mouseDownInCanvas(e); -} -void OpenGLCanvas::mouseDrag(const MouseEvent& e) {mouseDragInCanvas(e);} -void OpenGLCanvas::mouseMove(const MouseEvent& e) {mouseMoveInCanvas(e);} -void OpenGLCanvas::mouseUp(const MouseEvent& e) {mouseUpInCanvas(e);} -void OpenGLCanvas::mouseWheelMove(const MouseEvent& e, float a, float b) {mouseWheelMoveInCanvas(e,a,b);} + if (scrollPix + getHeight() > getTotalHeight() && getTotalHeight() > getHeight()) + scrollPix = getTotalHeight() - getHeight(); + else + scrollPix = 0; + + showScrollBars(); -void OpenGLCanvas::resized() -{ canvasWasResized(); } \ No newline at end of file diff --git a/Source/Processors/Visualization/OpenGLCanvas.h b/Source/Processors/Visualization/OpenGLCanvas.h index 3712b51d8bf2a1ca71d93d580d13ea256f7b56c9..a80f539fb7af2a6f27ec6381ea74ed5234159d22 100644 --- a/Source/Processors/Visualization/OpenGLCanvas.h +++ b/Source/Processors/Visualization/OpenGLCanvas.h @@ -40,24 +40,28 @@ public: virtual void refreshState() {}; - void mouseDownInCanvas(const MouseEvent& e); - void mouseDragInCanvas(const MouseEvent& e); - void mouseMoveInCanvas(const MouseEvent& e); - void mouseUpInCanvas(const MouseEvent& e); - void mouseWheelMoveInCanvas(const MouseEvent&, float, float); - - virtual void resized(); - virtual void mouseDown(const MouseEvent& e); - virtual void mouseDrag(const MouseEvent& e); - virtual void mouseMove(const MouseEvent& e); - virtual void mouseUp(const MouseEvent& e); - virtual void mouseWheelMove(const MouseEvent&, float, float); + + + void resized(); + virtual void canvasWasResized() { } + + void mouseDown(const MouseEvent& e); + void mouseDrag(const MouseEvent& e); + void mouseMove(const MouseEvent& e); + void mouseUp(const MouseEvent& e); + void mouseWheelMove(const MouseEvent&, float, float); + + virtual void mouseDownInCanvas(const MouseEvent& e) {} + virtual void mouseDragInCanvas(const MouseEvent& e) {} + virtual void mouseMoveInCanvas(const MouseEvent& e) {} + virtual void mouseUpInCanvas(const MouseEvent& e) {} + virtual void mouseWheelMoveInCanvas(const MouseEvent&, + float, + float) {} void startCallbacks(); void stopCallbacks(); - void canvasWasResized(); - int getScrollAmount() {return scrollPix;}; int getScrollBarWidth() {return scrollBarWidth;} void drawScrollBars(); @@ -69,6 +73,8 @@ public: protected: virtual int getTotalHeight() = 0; + int scrollPix; + void showScrollBars(); private: @@ -80,9 +86,8 @@ private: void drawScrollBar(float y1, float y2, float alpha); - void showScrollBars(); - int scrollBarWidth, scrollPix, scrollDiff, originalScrollPix; + int scrollBarWidth, scrollDiff, originalScrollPix; int scrollTime; bool showScrollTrack; diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33315e9aa1a1d1a5ed93554870a9f96c0db22b12 --- /dev/null +++ b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp @@ -0,0 +1,389 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "SpikeDisplayCanvas.h" + +SpikeDisplayCanvas::SpikeDisplayCanvas(SpikeDisplayNode* n) : processor(n), + xBuffer(25), yBuffer(25), newSpike(false), plotsInitialized(false), + totalScrollPix(0) +{ + + + + nSources = 0; //processor->getNumInputs(); + std::cout<<"SpikeDisplayNode has :"<<nSources<<" outputs!"<<std::endl; + + for (int i=0; i<nSources; i++) + nChannels[i] = processor->getNumberOfChannelsForInput(i); + + std::cout << "Setting num inputs on SpikeDisplayCanvas to " << nSources << std::endl; + + + +} + +SpikeDisplayCanvas::~SpikeDisplayCanvas() +{ + +} + +void SpikeDisplayCanvas::initializeSpikePlots(){ + std::cout<<"Initializing Plots"<<std::endl; + + + int nPlots = 6; + int nCols = 2; + + int totalWidth = getWidth(); + + int plotWidth = (totalWidth - yBuffer * ( nCols+1)) / nCols + .99; + int plotHeight = plotWidth / 2 + .5; + int rowCount = 0; + int i; + + for (i=0; i<nPlots; i++) + { + + StereotrodePlot p = StereotrodePlot( + xBuffer + i%nCols * (plotWidth + xBuffer) , + yBuffer + rowCount * (plotHeight + yBuffer), + plotWidth, + plotHeight); // deprecated conversion from string constant to char + SpikeObject tmpSpike; + generateEmptySpike(&tmpSpike, 4); + p.processSpikeObject(tmpSpike); + + plots.push_back(p); + + if (i%nCols == nCols-1) + rowCount++; + + } + totalHeight = yBuffer + rowCount * (plotHeight + yBuffer) + yBuffer; + + // Set the total height of the Canvas to the top of the top most plot + plotsInitialized = true; + repositionSpikePlots(); +} + +void SpikeDisplayCanvas::repositionSpikePlots(){ + + int nPlots = plots.size(); + int nCols = 2; + + int totalWidth = getWidth(); + + int plotWidth = (totalWidth - yBuffer * ( nCols+1)) / nCols + .99; + int plotHeight = plotWidth / 2 + .5; + int rowCount = 0; + + for (int i=0; i<plots.size(); i++) + { + + plots[i].setPosition( xBuffer + i%nCols * (plotWidth + xBuffer) , + yBuffer + rowCount * (plotHeight + yBuffer), + plotWidth, + plotHeight); // deprecated conversion from string constant to char + + if (i%nCols == nCols-1) + rowCount++; + } + + // Set the total height of the Canvas to the top of the top most plot + totalHeight = yBuffer + rowCount * (plotHeight + yBuffer) + yBuffer; +} + +void SpikeDisplayCanvas::newOpenGLContextCreated() +{ + + std::cout<<"SpikeDisplayCanvas::newOpenGLContextCreated()"<<std::endl; + setUp2DCanvas(); + activateAntiAliasing(); + + glClearColor (0.667, 0.698, 0.718, 1.0); + resized(); + endAnimation(); + //startTimer(50); + +} + +void SpikeDisplayCanvas::beginAnimation() +{ + std::cout << "Beginning animation." << std::endl; + + // displayBufferSize = displayBuffer->getNumSamples(); + + // screenBuffer->clear(); + + //displayBufferIndex = 0; +// screenBufferIndex = 0; + + startCallbacks(); +} + +void SpikeDisplayCanvas::endAnimation() +{ + std::cout << "Ending animation." << std::endl; + stopCallbacks(); +} + +void SpikeDisplayCanvas::update() +{ + // nChans = processor->getNumInputs(); + // sampleRate = processor->getSampleRate(); + + // std::cout << "Setting num inputs on SpikeDisplayCanvas to " << nChans << std::endl; + // if (nChans < 200 && nChans > 0) + // screenBuffer->setSize(nChans, 10000); + // //sampleRate = processor->getSampleRate(); + + // screenBuffer->clear(); + + repaint(); + + // totalHeight = (plotHeight+yBuffer)*nChans + yBuffer; +} + + +// Used for Plot specific commands, this commands target a specific PLOT and have +// no additional information, IE PARAM-> CLEAR val->plot6 +// for more complex messages use the other version of setParameter +void SpikeDisplayCanvas::setParameter(int param, float val) +{ + std::cout<<"Got Param:"<< param<< " with value:"<<val<<std::endl; + switch (param) + { + case SPIKE_CMD_CLEAR_ALL : + for (int i=0; i<plots.size(); i++) + plots[i].clear(); + break; + + case SPIKE_CMD_CLEAR_SEL: + //clear plot number val + break; + default: + std::cout<<"Unkown Commad specified! "<<param<<std::endl; + } +} + +void SpikeDisplayCanvas::setParameter(int param, int p2, int p3, float value){ + std::cout<<"Got Parameter:"<<param<<" p2:"<<p2<<" p3:"<<p3<<" value:"<<value<<std::endl; + switch (param){ + case SPIKE_CMD_PAN_AXES: + panPlot(p2, p3, value<=0); + break; + case SPIKE_CMD_ZOOM_AXES: + zoomPlot(p2, p3, value<=0); + break; + } +} + + +void SpikeDisplayCanvas::refreshState() +{ + // called when the component's tab becomes visible again + // displayBufferIndex = processor->getDisplayBufferIndex(); + // screenBufferIndex = 0; + + //resized(); + totalScrollPix = 0; +} + +void SpikeDisplayCanvas::canvasWasResized() +{ + repositionSpikePlots(); +} + +void SpikeDisplayCanvas::renderOpenGL() +{ + if(!plotsInitialized) + initializeSpikePlots(); + glClearColor (0.667, 0.698, 0.718, 1.0); + glClear(GL_COLOR_BUFFER_BIT); // clear buffers to preset values +// std::cout<<"SpikeDisplayCanvas::renderOpenGL"<<std::endl; + // Get Spikes from the processor + // Iterate through each spike, passing them individually to the appropriate plots and calling redraw before moving on to the next spike + + //while(processor->getNextSpike(&spike)) + //{ + + // Identify which plot the spike should go to + + // Distribute those spike to the appropriate plot object + + + SpikeObject tmpSpike; + for (int i=0; i<plots.size(); i++){ + generateSimulatedSpike(&tmpSpike, 0, 150); + plots[i].processSpikeObject(tmpSpike); + plots[i].redraw(); + drawPlotTitle( i ); + } + + //} + //std::cout << getHeight()<<" "<< getTotalHeight()<<" "<<std::endl; + drawScrollBars(); +} + +void SpikeDisplayCanvas::drawPlotTitle(int chan){ + + glViewport(0,0,getWidth(), getHeight()); + setViewportRange(0, 0, getWidth(), getHeight()); + + int x, y; + double w,h; + plots[chan].getPosition(&x,&y,&w,&h); + + float alpha = 0.50f; + + glColor4f(0.0f,0.0f,0.0f,alpha); + glRasterPos2f(x, y+h+2); + + String s = "Source:";//String("Channel "); + s += (chan+1); + + getFont(String("cpmono-bold"))->FaceSize(25); + getFont(String("cpmono-bold"))->Render(s); +} + +int SpikeDisplayCanvas::getTotalHeight() +{ + return totalHeight; +} + + +void SpikeDisplayCanvas::mouseDownInCanvas(const MouseEvent& e) +{ + + /* + Point<int> pos = e.getPosition(); + int xcoord = pos.getX(); + + if (xcoord < getWidth()-getScrollBarWidth()) + { + int chan = (e.getMouseDownY() + getScrollAmount())/(yBuffer+plotHeight); + + selectedChan = chan; + + repaint(); + }*/ + +} + +// void SpikeDisplayCanvas::mouseDrag(const MouseEvent& e) {mouseDragInCanvas(e);} +// void SpikeDisplayCanvas::mouseMove(const MouseEvent& e) {mouseMoveInCanvas(e);} +void SpikeDisplayCanvas::mouseUp(const MouseEvent& e) { + // std::cout<<"Mouse Event!"<<std::endl; + + // bool inout = false; + + // if (e.getMouseDownX() < getWidth()/2) + // inout = false; + // else + // inout = true; + + // if (e.getMouseDownY() < getHeight()/2) + // zoomPlot(0,0, inout); + // else + // panPlot(0,0,inout); +} +void SpikeDisplayCanvas::mouseWheelMove(const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { + + // std::cout<<"Mouse Wheel Move:"<< wheelIncrementX<<","<<wheelIncrementY; + // std::cout<<" Scroll Pix:"<<scrollPix<<std::endl; + + int scrollAmount = 0; + // std::cout<<getTotalHeight()<<" "<<getHeight()<<std::endl; + + if (getTotalHeight() > getHeight()) { + //if (wheelIncrementY > 0 ) + scrollAmount += int(100.0f*wheelIncrementY); + //else if (wheelIncrementY < 0) + + totalScrollPix += scrollAmount; + + // don't let the user scroll too far down + int minScrollDown = (-1 * totalHeight) + getHeight(); + int maxScrollUp = 0; // never scroll plots up, there is nothing below the bottom plot + + // std::cout<<"TotalScrollPix:"<<totalScrollPix<<" min:"<<minScrollDown<<" max:"<<maxScrollUp<<std::endl; + + if (totalScrollPix < minScrollDown){ + totalScrollPix= minScrollDown; + scrollAmount = 0; + } + + else if (totalScrollPix > maxScrollUp) + { + totalScrollPix = maxScrollUp; + scrollAmount = 0; + } + + for (int i=0; i<plots.size(); i++){ + int x,y; + double w,h; + plots[i].getPosition(&x, &y, &w, &h); + plots[i].setPosition(x,y+scrollAmount, w, h); + } + + scrollPix = 0;//totalScrollPix; + + repaint(); + + showScrollBars(); + + } + + mouseWheelMoveInCanvas(e, wheelIncrementX, wheelIncrementY); +} + +void SpikeDisplayCanvas::panPlot(int p, int c, bool up){ + std::cout<<"SpikeDisplayCanvas::panPlot()"<<std::endl; + if (p<0 || p>plots.size()) + return; + plots[p].pan(c, up); + +} +void SpikeDisplayCanvas::zoomPlot(int p, int c, bool in){ + std::cout<<"SpikeDisplayCanvas::panPlot()"<<std::endl; + if (p<0 || p>plots.size()) + return; + plots[p].zoom(c, in); +} + +// void SpikeDisplayCanvas::resized() +// { +// //screenBuffer = new AudioSampleBuffer(nChans, getWidth()); + +// // glClear(GL_COLOR_BUFFER_BIT); + +// // //int h = getParentComponent()->getHeight(); + +// // if (scrollPix + getHeight() > getTotalHeight() && getTotalHeight() > getHeight()) +// // scrollPix = getTotalHeight() - getHeight(); +// // else +// // scrollPix = 0; + +// // showScrollBars(); +// canvasWasResized(); +// } \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.h b/Source/Processors/Visualization/SpikeDisplayCanvas.h new file mode 100644 index 0000000000000000000000000000000000000000..c142b3566c7c3aa9a71e6dbcce56e0df5803aa90 --- /dev/null +++ b/Source/Processors/Visualization/SpikeDisplayCanvas.h @@ -0,0 +1,127 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef SPIKEDISPLAYCANVAS_H_ +#define SPIKEDISPLAYCANVAS_H_ + +#include "../../../JuceLibraryCode/JuceHeader.h" + +#include "../SpikeDisplayNode.h" +#include "SpikePlotting/ElectrodePlot.h" +#include "SpikePlotting/StereotrodePlot.h" +#include "SpikePlotting/TetrodePlot.h" +#include "SpikeObject.h" + +#include "Visualizer.h" +#include <vector> + + /** + + Displays spike waveforms and projections. + + @see SpikeDisplayNode, SpikeDisplayEditor, Visualizer + +*/ + +#define MAX_NUMBER_OF_SPIKE_SOURCES = 128; + +class SpikeDisplayNode; + +class SpikeDisplayCanvas : public Visualizer + +{ +public: + SpikeDisplayCanvas(SpikeDisplayNode* n); + ~SpikeDisplayCanvas(); + void newOpenGLContextCreated(); + void renderOpenGL(); + + void beginAnimation(); + void endAnimation(); + + void refreshState(); + + void update(); + + void setParameter(int, float); + void setParameter(int, int, int, float); + + void panPlot(int, int, bool); + void zoomPlot(int, int, bool); + +private: + + int xBuffer, yBuffer; + + bool plotsInitialized; + + bool newSpike; + SpikeObject spike; + SpikeDisplayNode* processor; + std::vector<StereotrodePlot> plots; + + int totalScrollPix; + // AudioSampleBuffer* displayBuffer; + // ScopedPointer<AudioSampleBuffer> screenBuffer; + // MidiBuffer* eventBuffer; + + // void setViewport(int chan); + // void drawBorder(bool isSelected); + // void drawChannelInfo(int chan, bool isSelected); + // void drawWaveform(int chan, bool isSelected); + + void drawPlotTitle(int chan); + //void drawTicks(); + + // bool checkBounds(int chan); + + // void updateScreenBuffer(); + // int screenBufferIndex; + // int displayBufferIndex; + // int displayBufferSize; + + int totalHeight; + // int selectedChan; + + int getTotalHeight(); + + int nSources; + int nChannels[MAX_NUMBER_OF_SPIKE_CHANNELS]; + + void initializeSpikePlots(); + void repositionSpikePlots(); + + void canvasWasResized(); + void mouseDownInCanvas(const MouseEvent& e); + // void mouseDrag(const MouseEvent& e); + // void mouseMove(const MouseEvent& e); + void mouseUp(const MouseEvent& e); + void mouseWheelMove(const MouseEvent&, float, float); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayCanvas); + +}; + + + +#endif // SPIKEDISPLAYCANVAS_H_ diff --git a/Source/Processors/Visualization/SpikeObject.cpp b/Source/Processors/Visualization/SpikeObject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a13c839a66631c6e17b40dcf4df35d29c964a3ba --- /dev/null +++ b/Source/Processors/Visualization/SpikeObject.cpp @@ -0,0 +1,220 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "SpikeObject.h" +#include <iostream> +#include "memory.h" +#include <stdlib.h> +#include "time.h" + +// Simple method for serializing a SpikeObject into a string of bytes +bool packSpike(SpikeObject *s, char* buffer, int bufferSize){ + + int idx = 0; + memcpy(buffer+idx, &(s->timestamp), 4); + idx += 4; + + memcpy(buffer+idx, &(s->source), 2); + idx +=2; + + memcpy(buffer+idx, &(s->nChannels), 2); + idx +=2; + + memcpy(buffer+idx, &(s->nSamples), 2); + idx +=2; + + memcpy(buffer+idx, &(s->data), s->nChannels * s->nSamples * 2); + idx += s->nChannels * s->nSamples * 2; + + memcpy(buffer+idx, &(s->gain), s->nChannels); + idx += s->nChannels; + + memcpy(buffer+idx, &(s->threshold), s->nChannels); + idx += s->nChannels; + +if (idx>=bufferSize) + std::cout<<"Buffer Overrun! More data packaged than space provided!"<<std::endl; + // makeBufferValid(buffer, bufferSize); + +} + +// Simple method for deserializing a string of bytes into a Spike object +bool unpackSpike(SpikeObject *s, char* buffer, int bufferSize){ + // if !(isBufferValid(buffer, bufferSize)); + // return false; + + int idx = 0; + + memcpy( &(s->timestamp), buffer+idx, 4); + idx += 4; + + memcpy( &(s->source), buffer+idx, 2); + idx += 2; + + memcpy( &(s->nChannels), buffer+idx, 2); + idx +=2; + + memcpy( &(s->nSamples), buffer+idx, 2); + idx +=2; + + memcpy( &(s->data), buffer+idx, s->nChannels * s->nSamples * 2); + idx += s->nChannels * s->nSamples * 2; + + memcpy( &(s->gain), buffer+idx, s->nChannels * 2); + idx += s->nChannels * 2; + + memcpy( &(s->threshold), buffer+idx, s->nChannels *2); + idx += s->nChannels * 2; + + if (idx>=bufferSize) + std::cout<<"Buffer Overrun! More data extracted than was given!"<<std::endl; + +} + +// Checks the validity of the buffer, this should be run before unpacking and after packing the buffer +bool isBufferValid(char *buffer, int bufferSize){ + + if (! CHECK_BUFFER_VALIDITY ) + return true; + + uint16_t runningSum = 0; + uint16_t value = 0; + + int idx = 0; + + for (idx; idx<bufferSize-2; idx+=2){ + memcpy(buffer + idx, &value, 2); + runningSum += value; + } + + uint16_t integrityCheck = 0; + memcpy(buffer + idx, &integrityCheck, 2); + + std::cout<<integrityCheck<<" == "<< runningSum <<std::endl; + return (integrityCheck == runningSum); +} + +void makeBufferValid(char *buffer, int bufferSize){ + if (! CHECK_BUFFER_VALIDITY ) + return; + + uint16_t runningSum = 0; + uint16_t value = 0; + + int idx = 0; + + for (idx; idx<bufferSize-2; idx+=2){ + memcpy(buffer + idx, &value, 2); + runningSum += value; + } + + memcpy(&runningSum, buffer + idx, 2); + +} + +void generateSimulatedSpike(SpikeObject *s, uint64_t timestamp, int noise) +{ + //std::cout<<"generateSimulatedSpike()"<<std::endl; + + uint16_t trace[][32] = + { + { 880, 900, 940, 1040, 1290, 1790, 2475, 2995, 3110, 2890, + 2505, 2090, 1720, 1410, 1155, 945, 775, 635, 520, 420, + 340, 265, 205, 155, 115, 80, 50, 34, 10, 34, 50, 80}, + { 1040, 1090, 1190, 1350, 1600, 1960, 2380, 2790, 3080, 3140, + 2910, 2430, 1810, 1180, 680, 380, 270, 320, 460, 630, + 770, 870, 940, 970, 990, 1000, 1000, 1000, 1000, 1000, 1000, 1000}, + { 1000, 1000, 1000, 1000, 1000, 1040, 1140, 1440, 2040, 2240, + 2400, 2340, 2280, 1880, 1640, 920, 520, 300, 140, 040, + 20, 20, 40, 100, 260, 500, 740, 900, 960, 1000, 1000, 1000} + }; + + + // We don't want to shift the waveform but scale it, and we don't want to scale + // the baseline, just the peak of the waveform + float scale[32] = + { 1.0, 1.0, 1.0, 1.0, 1.1, 1.2, 1.3, 1.5, 1.7, 2.0, 2.1, 2.2, 2.1, 2.0, 1.7, 1.5, + 1.3, 1.2, 1.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + + uint16_t gain = 2000; + + s->timestamp = timestamp; + s->source = 0; + s->nChannels = 4; + s->nSamples = 32; + int idx=0; + + int waveType = rand()%2; // Pick one of the three predefined waveshapes to generate + int shift = 1000; + + for (int i=0; i<4; i++) + { + s->gain[i] = gain; + s->threshold[i] = 4000; + double scaleExponent = (double)(rand()%26+2) / 10.0f; // Scale the wave between 50% and 150% + + for (int j=0; j<32; j++){ + + int n = 0; + if (noise>0){ + n = rand() % noise - noise/2; + } + + s->data[idx] = (trace[waveType][j] + n) * pow(scale[j],scaleExponent) + shift; + idx = idx+1; + } + } + +} +void generateEmptySpike(SpikeObject *s, int nChannels){ + + s->timestamp = 0; + s->source = 0; + s->nChannels = 4; + s->nSamples = 32; + + int idx = 0; + for (int i=0; i<4; i++) + { + s->gain[i] = 0; + s->threshold[i] = 0; + for (int j=0; j<32; j++){ + s->data[idx] = 0; + idx = idx+1; + } + } +} + + +// std::ostream& operator<<(std::ostream &strm, const SpikeObject s){ + +// strm << " SpikeObject:\n"; +// strm << "\tTimestamp:" << s.timestamp; +// strm << "\tSource:" << s.source; +// strm << "\tnChannels:" <<s.nChannels; +// strm <<"\tnSamples" << s.nSamples; +// strm <<"\n\t 8 Data Samples:"; +// for (int i=0; i<8; i++) +// strm << s.data[i]<<" "; +// return strm; +// } diff --git a/Source/Processors/Visualization/SpikeObject.h b/Source/Processors/Visualization/SpikeObject.h new file mode 100644 index 0000000000000000000000000000000000000000..f2b517ae02125e3efdd3180994866ec2eb76d49b --- /dev/null +++ b/Source/Processors/Visualization/SpikeObject.h @@ -0,0 +1,85 @@ +/* + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2012 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef SPIKEOBJECT_H_ +#define SPIKEOBJECT_H_ + +#include <stdint.h> +#include <math.h> + +#define MAX_NUMBER_OF_SPIKE_CHANNELS 4 +#define MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES 256 +#define CHECK_BUFFER_VALIDITY true + +struct SpikeObject{ + + uint64_t timestamp; + uint16_t source; + uint16_t nChannels; + uint16_t nSamples; + uint16_t data[MAX_NUMBER_OF_SPIKE_CHANNELS * MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES]; + uint16_t gain[MAX_NUMBER_OF_SPIKE_CHANNELS]; + uint16_t threshold[MAX_NUMBER_OF_SPIKE_CHANNELS]; + +}; + +/* + For transmission between processors SpikeObjects must be packaged up into buffers that can fit into MidiEvents + The following two methods can be used to package the above spike object into a buffer and unpackage a buffer + into a SpikeObject. + + The buffer is LittleEndian (thank Intel) and the byte order is the same as the SpikeObject definition. + IE. the first 2 bytes are the timestamp, the next two bytes are the source identifier, etc... with the last + set of bytes corresponding to the thresholds of the different channels. + + Finally the buffer will have an additional byte on the end that is used to check the integerity of the entire package. + The way this works is the buffer is divivded up into a series of 16 bit unsigned integers. The sum of all these integers + (except the last 16 bit integer) is taken and the sum should equal that 16 bit integer. If not then the data is corrupted + and should be dropped or delt with another way. +*/ + +// Simple method for serializing a SpikeObject into a string of bytes, returns true is the packaged spike buffer is valid +bool packSpike(SpikeObject *s, char* buffer, int bufferLength); + +// Simple method for deserializing a string of bytes into a Spike object, returns true is the provided spike buffer is valid +bool unpackSpike(SpikeObject *s, char* buffer, int bufferLength); + +// Checks the validity of the buffer, this should be run before unpacking the buffer +bool isBufferValid(char *buffer, int bufferLength); + +// Computes the validity value for the buffer, this should be called after packing the buffer +void makeBufferValid(char *buffer, int bufferLength); + +// Help function for generating fake spikes in the absence of a real spike source. +// Can be used to generate a sign wave with a fixed Frequency of 1000 hz or a basic spike waveform +// Additionally noise can be added to the waveform for help in diagnosing projection plots +void generateSimulatedSpike(SpikeObject *s, uint64_t timestamp, int noise); + +// Define the << operator for the SpikeObject +// std::ostream& operator<<(std::ostream &strm, const SpikeObject s); + +// Helper function for zeroing out a spike object with a specified number of channels +void generateEmptySpike(SpikeObject *s, int nChannels); + + +#endif //SPIKEOBJECT_H_ \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99995ba290bd97b2a8f213a8fba7ad0e5d3b4c28 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp @@ -0,0 +1,90 @@ +#include "BaseUIElement.h" + +BaseUIElement::BaseUIElement(): + xpos(0), ypos(0), yOffset(0), + width(100), height(100), enabled(true), padding(0) +{ +} + +BaseUIElement::BaseUIElement(int x, int y, double w, double h): + yOffset(0), enabled(true), padding(0) +{ + xpos = x+padding; + ypos = y+padding; + width = w-padding*2; + height = h-padding*2; +} +BaseUIElement::BaseUIElement(int x, int y, double w, double h, int p): + enabled(true), padding(0) +{ + xpos = x+padding; + ypos = y+padding; + width = w-padding*2; + height = h-padding*2; +} + +void BaseUIElement::redraw(){ +// std::cout<<"BaseUIElement::redraw(), Position:"<<xpos<<","<<ypos<<" : "<<width<<","<<height<<std::endl; + setGlViewport(); + + // if (clearNextDraw || !clearNextDraw){ + // clearNextDraw = false; + glColor3f(0.0, 0.0, 0.0); + glRecti(-1,-1,1,1); + + + // } +} +void BaseUIElement::drawElementEdges(){ + // std::cout<<"BaseUIElement::drawBaseUIElementEdges(), Position:"<<xpos<<","<<ypos<<" : "<<width<<","<<height<<std::endl; + glColor3f(1.0, 1.0, 1.0); + setGlViewport(); + glLineWidth(2); + drawViewportEdge(); +} +void BaseUIElement::setEnabled(bool e){ + enabled = e; +} +bool BaseUIElement::getEnabled(){ + return enabled; +} +void BaseUIElement::setGlViewport(){ + + glLoadIdentity(); + glViewport(xpos, ypos, width, height); + + // std::cout<<xpos<<"x"<<ypos<<"-"<<width<<"x"<<height<<"\t"<<BaseUIElementName<<std::endl; +} +void BaseUIElement::setPosition(int x, int y, double w, double h){ + xpos = x+padding; + ypos = y+padding; + width = w - padding*2; + height = h - padding*2; +} + +void BaseUIElement::getPosition(int *x, int *y, double *w, double *h){ + *x = xpos; + *y = ypos; + *w = width; + *h = height; +} +// void BaseUIElement::clearOnNextDraw(bool c){ +// clearNextDraw = c; +// } + +bool BaseUIElement::hitTest(int x, int y){ + return (x>xpos && x<xpos+width) && (y>ypos && y<ypos+height); +} + +double BaseUIElement::getHeight(){ + return height; +} +double BaseUIElement::getWidth(){ + return width; +} +int BaseUIElement::getX(){ + return xpos; +} +int BaseUIElement::getY(){ + return ypos; +} diff --git a/Source/Processors/Visualization/SpikePlotting/BaseUIElement.h b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.h new file mode 100644 index 0000000000000000000000000000000000000000..b69a491dda3b0128d928c3191f876fd125317c8c --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.h @@ -0,0 +1,40 @@ +#ifndef BASEUIELEMENT_H_ +#define BASEUIELEMENT_H_ + +#include "PlotUtils.h" + + +class BaseUIElement{ + +protected: + int xpos, ypos, yOffset; + double height, width; + bool enabled; + double padding; + + void setGlViewport(); + +public: + BaseUIElement(); + BaseUIElement(int x, int y, double w, double h); + BaseUIElement(int x, int y, double w, double h, int p); + void redraw(); + void drawElementEdges(); + void setEnabled(bool e); + bool getEnabled(); + void setPosition(int x, int y, double w, double h); + void getPosition(int*, int*, double*, double*); + double getHeight(); + double getWidth(); + int getX(); + int getY(); + + // void clearOnNextDraw(bool); + // bool clearNextDraw; + bool hitTest(int x, int y); + +}; + + + +#endif // BaseUIElement_H_ diff --git a/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e12df2daf39ed012f8e6fcc94c292842ace57ba8 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp @@ -0,0 +1,257 @@ +#include "ElectrodePlot.h" +#include "../SpikeObject.h" +#include "PlotUtils.h" + +ElectrodePlot::ElectrodePlot(): + BaseUIElement(), limitsChanged(true) +{ +} + +ElectrodePlot::ElectrodePlot(int x, int y, int w, int h): + BaseUIElement(x,y,w,h,1), limitsChanged(true) +{ + + initAxes(); +} + +ElectrodePlot::~ElectrodePlot(){ +} + +// Each plot needs to update its children axes when its redraw gets called. +// it also needs to call the parent plot when children axes get added it +// should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3 +// should go by default. This isn't as general as it should be but its a good push in +// the right direction + +void ElectrodePlot::redraw(){ + //std::cout<<"ElectrodePlot() starting drawing"<<std::endl;\ + BaseUIElement::clearNextDraw = true; + BaseUIElement::redraw(); + + axes.redraw(); +} + +// This would normally happen for collection of axes but an electrode plot doesn't have a collection instead its a single axes +void ElectrodePlot::processSpikeObject(SpikeObject s){ + //std::cout<<"ElectrdePlot::processSpikeObject()"<<std::endl; + axes.updateSpikeData(s); +} + +void ElectrodePlot::setEnabled(bool e){ + BaseUIElement::enabled = e; + + axes.setEnabled(e); +} + +bool ElectrodePlot::getEnabled(){ + return BaseUIElement::enabled; +} + + +void ElectrodePlot::initAxes(){ + initLimits(); + + int minX = BaseUIElement::xpos; + int minY = BaseUIElement::ypos; + + double axesWidth = BaseUIElement::width; + double axesHeight = BaseUIElement::height; + + + axes = WaveAxes(minX, minY, axesWidth, axesHeight, WAVE1); + + //axes.setEnabled(false); + axes.setYLims(-1*pow(2,11), pow(2,14)*1.6); + axes.setWaveformColor(1.0, 1.0, 1.0); + +} + +void ElectrodePlot::setPosition(int x, int y, double w, double h){ + BaseUIElement::setPosition(x,y,w,h); + int minX = BaseUIElement::xpos; + int minY = BaseUIElement::ypos; + + double axesWidth = BaseUIElement::width; + double axesHeight = BaseUIElement::height; + + axes.setPosition(minX, minY, axesWidth, axesHeight); + +} + +int ElectrodePlot::getNumberOfAxes(){ + return 1;; +} + + +void ElectrodePlot::initLimits(){ + for (int i=0; i<4; i++) + { + limits[i][0] = -1*pow(2,11); + limits[i][1] = pow(2,14); + } + +} + +void ElectrodePlot::getPreferredDimensions(double *w, double *h){ + *w = 75; + *h = 75; +} +// void ElectrodePlot::mouseDown(int x, int y){ + +// // selectedAxesN = -1; +// // std::list<GenericAxes>::iterator i; +// // int idx=-1; +// // bool hit = false; + +// // selectedAxes = NULL; +// // for (i=axesList.begin(); i!=axesList.end(); ++i) +// // { +// // if (i->hitTest(x,y)) +// // { +// // selectedAxes = addressof(*i); +// // selectedAxesN = i->getType(); +// // hit = true; +// // // break; +// // } +// // idx++; +// // } +// // if (!hit) +// // selectedAxes = NULL; +// // if (selectedAxes != NULL) +// // std::cout<<"ElectrodePlot::mouseDown() hit:"<<selectedAxes<<" AxesType:"<<selectedaxes.getType()<<std::endl; +// // else +// // std::cout<<"ElectrodePlot::mouseDown() NO HIT!"<<std::endl; + +// } +// void ElectrodePlot::mouseDragX(int dx, bool shift, bool ctrl){ + +// // if (selectedAxes == NULL || dx==0) +// // return; +// // // zoomAxes(selectedaxes.getType(), true, dx>0); +// // if (shift) +// // zoomAxes(selectedAxesN, true, dx); +// // if (ctrl) +// // panAxes(selectedAxesN, true, dx); + +// } +// void ElectrodePlot::mouseDragY(int dy, bool shift, bool ctrl){ +// if (selectedAxes == NULL || dy==0) +// return; +// if(shift) +// zoomAxes(selectedAxesN, false, dy); +// if(ctrl) +// panAxes(selectedAxesN, false, dy); +// } + +// void ElectrodePlot::zoomAxes(int n, bool xdim, int zoom){ +// // std::cout<<"ElectrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl; +// // If trying to zoom an invalid axes type +// if (n<WAVE1 || n>PROJ3x4) +// return; +// if (n<=WAVE4) +// zoomWaveform(n, xdim, zoom); +// else +// zoomProjection(n, xdim, zoom); +// } + +// void ElectrodePlot::zoomWaveform(int n, bool xdim, int zoom){ + +// // waveform plots don't have a xlimits +// if (xdim) +// return; +// // std::cout<<"Zooming Waveform:"<<n<<" zoomin:"<<zoomin<<" "; +// double min, max; + +// if(xdim) +// return; + +// min = limits[n][0]; +// max = limits[n][1]; + +// double mean = (max + min)/2.0f; +// double delta = max - mean; +// delta = delta / pow(.99, -1*zoom); + +// min = mean - delta; +// max = mean + delta; + +// limits[n][0] = min; +// limits[n][1] = max; + +// limitsChanged = true; +// } + +// void ElectrodePlot::panAxes(int n, bool xdim, int panval){ +// // std::cout<<"ElectrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl; +// // If trying to zoom an invalid axes type +// if (n<WAVE1 || n>PROJ3x4) +// return; +// if (n<=WAVE4) +// panWaveform(n, xdim, panval); +// else +// panProjection(n, xdim, panval); +// } + +// void ElectrodePlot::panWaveform(int n, bool xdim, int pan){ + +// // waveform plots don't have a xlimits +// if (xdim) +// return; +// // std::cout<<"Panning Waveform:"<<n<<" pan:"<<pan<<" "<<std::endl; +// double min, max; + +// if(xdim) +// return; + +// min = limits[n][0]; +// max = limits[n][1]; + +// double dy = max-min; + +// // Need to grab something if pan event is driven by the keyboard, which means that all the plots are getting panned so this should be okay +// if (selectedAxes == NULL) +// selectedAxes = &axesList.front(); + +// double yPixels = (BaseUIElement::height - titleHeight)/2.0; + +// double pixelWidth = -1 * dy/yPixels; + +// double delta = pan * pixelWidth; +// min = min + delta; +// max = max + delta; + +// limits[n][0] = min; +// limits[n][1] = max; + +// limitsChanged = true; +// } + + + +bool ElectrodePlot::processKeyEvent(SimpleKeyEvent k){ + // std::cout<<"Key:"<<(char)k.key<<std::endl; + // switch(k.key) + // { + // case '=': + // for (int i=0; i<=WAVE4; i++) + // zoomWaveform(i, false, 3); + // break; + // case '+': + // for (int i=0; i<=WAVE4; i++) + // panWaveform(i, false, 3); + // break; + // case '-': + // for (int i=0; i<=WAVE4; i++) + // zoomWaveform(i, false, -3); + // break; + // case '_': + // for (int i=0; i<=WAVE4; i++) + // panWaveform(i, false, -3); + // break; + // case 'C': + // clearOnNextDraw(true); + // break; + // } +} + + diff --git a/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h new file mode 100644 index 0000000000000000000000000000000000000000..6377aa42c15b538396966600feebcca7d6043a2e --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h @@ -0,0 +1,66 @@ +#ifndef ELECTRODE_PLOT_H +#define ELECTRODE_PLOT_H + +#if defined(__linux__) + #include <GL/glut.h> +#else + #include <GLUT/glut.h> +#endif +#include <list> +#include <math.h> + +#include "WaveAxes.h" +#include "BaseUIElement.h" +#include "PlotUtils.h" +#include "SimpleKeyEvent.h" + + +class ElectrodePlot : public BaseUIElement{ + + bool enabled; + + bool limitsChanged; + double limits[1][2]; + + WaveAxes axes; + + + + // void zoomAxes(int n, bool xdim, int zoomval); + // void zoomProjection (int n, bool xdim, int zoomval); + // void zoomWaveform (int n, bool xdim, int zoomval); + + // void panAxes(int n, bool xdim, int panval); + // void panProjection (int n, bool xdim, int panval); + // void panWaveform(int n, bool xdim, int panval); + + void initLimits(); + +public: + ElectrodePlot(); + ElectrodePlot(int x, int y,int w,int h); + ~ElectrodePlot(); + + void initAxes(); + void redraw(); + void setEnabled(bool enabled); + bool getEnabled(); + void setPosition(int,int,double,double); + + void getPreferredDimensions(double*, double*); + + int getNumberOfAxes(); + + void mouseDown(int x, int y); + + void mouseDragX(int dx, bool shift, bool ctr); + void mouseDragY(int dy, bool shift, bool ctr); + + bool processKeyEvent(SimpleKeyEvent k); + + void processSpikeObject(SpikeObject s); +}; + + + +#endif diff --git a/Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp b/Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dfb7a815e63cabf7a5cdc8671783af56e786b0f2 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp @@ -0,0 +1,68 @@ +#include "GenericAxes.h" + +GenericAxes::GenericAxes(): + BaseUIElement(), + type(0), + gotFirstSpike(false) +{ + ylims[0] = 0; + ylims[1] = 1; + loadFont(); +} + +GenericAxes::GenericAxes(int x, int y, double w, double h, int t): + BaseUIElement(x,y,w,h), + gotFirstSpike(false) +{ + type = t; + loadFont(); +} +GenericAxes::~GenericAxes(){ + //delete font; +} +void GenericAxes::updateSpikeData(SpikeObject newSpike){ + if (!gotFirstSpike){ + gotFirstSpike = true; + } + + s = newSpike; +} + +void GenericAxes::loadFont(){ + const unsigned char* buffer = reinterpret_cast<const unsigned char*>(BinaryData::cpmono_plain_otf); + size_t bufferSize = BinaryData::misoregular_ttfSize; + font = new FTPixmapFont(buffer, bufferSize); +} + +void GenericAxes::setYLims(double ymin, double ymax){ + ylims[0] = ymin; + ylims[1] = ymax; +} +void GenericAxes::getYLims(double *min, double *max){ + *min = ylims[0]; + *max = ylims[1]; +} +void GenericAxes::setXLims(double xmin, double xmax){ + xlims[0] = xmin; + xlims[1] = xmax; +} +void GenericAxes::getXLims(double *min, double *max){ + *min = xlims[0]; + *max = xlims[1]; +} + +void GenericAxes::setType(int t){ + if (t<WAVE1 || t>PROJ3x4){ + std::cout<<"Invalid Axes type specified"; + return; + } + type = t; +} + +int GenericAxes::getType(){ + return type; +} + +void GenericAxes::setPosition(int x, int y, double w, double h){ + BaseUIElement::setPosition(x,y,w,h); +} diff --git a/Source/Processors/Visualization/SpikePlotting/GenericAxes.h b/Source/Processors/Visualization/SpikePlotting/GenericAxes.h new file mode 100644 index 0000000000000000000000000000000000000000..3ef432ed9ab4a6da1d751631da966987f6638b13 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/GenericAxes.h @@ -0,0 +1,60 @@ +#ifndef GENERIC_AXES_H_ +#define GENERIC_AXES_H_ + + +#if defined(__linux__) + #include <GL/glut.h> +#else + #include <GLUT/glut.h> +#endif +#include <stdlib.h> +#include <FTGL/ftgl.h> +#include "../../../../JuceLibraryCode/JuceHeader.h" + +#include "../SpikeObject.h" + +#include "BaseUIElement.h" +#include "PlotUtils.h" + + +class GenericAxes: public BaseUIElement{ + +protected: + double xlims[2]; + double ylims[2]; + SpikeObject s; + + bool gotFirstSpike; + + int type; + virtual void plot(){} + + FTPixmapFont* font; + void loadFont(); + + +public: + GenericAxes(); + GenericAxes(int x, int y, double w, double h, int t); + ~GenericAxes(); + + void updateSpikeData(SpikeObject s); + + virtual void redraw(){} + + void setXLims(double xmin, double xmax); + void getXLims(double *xmin, double *xmax); + void setYLims(double ymin, double ymax); + void getYLims(double *ymin, double *ymax); + + void setType(int type); + int getType(); + + + void setPosition(int,int,double,double); + +}; + + + +#endif diff --git a/Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp b/Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8da171314791dfc157b19606d578972e45af703e --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp @@ -0,0 +1,227 @@ +#include "PlotUtils.h" + +void checkGlError(){ + GLenum errCode; + const GLubyte *errString; + if ((errCode = glGetError()) != GL_NO_ERROR) { + errString = gluErrorString(errCode); + fprintf (stderr, "OpenGL Error: %s\n", errString); + exit(1); + } + else + std::cout<<"OpenGL Okay!"<<std::endl; +} + +void drawString(float x, float y, void *f, const char *string){ + glRasterPos2f(x, y); + int len = strlen(string); + // glColor3f(1.0, 1.0, 1.0); + for (int i = 0; i < len; i++) { + //glutBitmapCharacter(f, string[i]); + } +} + +void drawString(float x, float y, int size, String s, FTPixmapFont* f){ + + glRasterPos2f(x, y); + + f->FaceSize(size); + f->Render(s); +} + +void drawViewportEdge(){ + glPushMatrix(); + glLoadIdentity(); + + glBegin(GL_LINE_LOOP); + glVertex2f(-.995, -.995); + glVertex2f( .995, -.995); + glVertex2f( .995, .995); + glVertex2f(-.995, .995); + glEnd(); + + glPopMatrix(); +} + +void drawViewportCross(){ + glColor3f(0.0,1.0,1.0); + + glPushMatrix(); + glLoadIdentity(); + + glBegin(GL_LINE_LOOP); + glVertex2f(-.995, -.995); + glVertex2f( .995, .995); + glVertex2f( .995, -.995); + glVertex2f(-.995, .995); + glEnd(); + + glPopMatrix(); +} + +void setViewportRange(int xMin,int yMin,int xMax,int yMax){ + + float dx = xMax-xMin; + float dy = yMax-yMin; + +// printf("Setting viewport to:%d,%d %d,%d with dims%d,%d %d,%d\n", x,y,w,h, xMin, xMin, xMax,yMax); +// printf("Dx:%f Dy:%f, Scaling viewport by:%f,%f \n", dx,dy,2.0/dx, 2.0/dy); + glLoadIdentity(); + glTranslatef(-1.0,-1.0,0.0); + glScalef(2.0f/dx, 2.0f/dy, 1.0); + glTranslatef(0-xMin, 0-yMin, 0); + +} +int roundUp(int numToRound, int multiple) +{ + if(multiple == 0) + { + return numToRound; + } + + int remainder = numToRound % multiple; + if (remainder == 0) + return numToRound; + return numToRound + multiple - remainder; +} + +double ad16ToUv(int x, int gain){ + int result = (double)(x * 20e6) / (double)(gain * pow(2,16)); + return result; +} + +void makeLabel(int val, int gain, bool convert, char * s){ + if (convert){ + double volt = ad16ToUv(val, gain)/1000.; + if (abs(val)>1e6){ + val = val/(1e6); + sprintf(s, "%.2fV", volt); + } + else if(abs(val)>1e3){ + val = val/(1e3); + sprintf(s, "%.2fmV", volt); + } + else + sprintf(s, "%.2fuV", volt); + } + else + sprintf(s,"%d", (int)val); +} + +void n2ProjIdx(int proj, int *p1, int *p2){ + int d1, d2; + if (proj==PROJ1x2){ + d1 = 0; + d2 = 1; + } + else if(proj==PROJ1x3){ + d1 = 0; + d2 = 2; + } + else if(proj==PROJ1x4){ + d1 = 0; + d2 = 3; + } + else if(proj==PROJ2x3){ + d1 = 1; + d2 = 2; + } + else if(proj==PROJ2x4){ + d1 = 1; + d2 = 3; + } + else if (proj==PROJ3x4){ + d1 = 2; + d2 = 3; + } + else{ + std::cout<<"Invalid projection:"<<proj<<"! Cannot determine d1 and d2"<<std::endl; + *p1 = -1; + *p2 = -1; + return; + } + *p1 = d1; + *p2 = d2; +} + + +bool isFrameBufferExtensionSupported(){ + + std::cout<<"Checking to see if the OpenGL Frame Buffer Extension is Supported"<<std::endl; + + char* str = 0; + char* tok = 0; + + std::string fboExt = "GL_EXT_framebuffer_object"; + + str = (char*)glGetString(GL_EXTENSIONS); + + if(str) + { + std::vector <std::string> extensions; + tok = strtok((char*)str, " "); + while(tok) + { + + std::string ext = tok; + + if (ext == fboExt) + return true; + + tok = strtok(0, " "); + } + return false; + } + else + return false; +} + +bool checkFramebufferStatus() +{ + // check FBO status + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + return status == GL_FRAMEBUFFER_COMPLETE_EXT; + + switch(status) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + std::cout << "Framebuffer complete." << std::endl; + return true; + + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + std::cout << "[ERROR] Framebuffer incomplete: Attachment is NOT complete." << std::endl; + return false; + + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + std::cout << "[ERROR] Framebuffer incomplete: No image is attached to FBO." << std::endl; + return false; + + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + std::cout << "[ERROR] Framebuffer incomplete: Attached images have different dimensions." << std::endl; + return false; + + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + std::cout << "[ERROR] Framebuffer incomplete: Color attached images have different internal formats." << std::endl; + return false; + + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + std::cout << "[ERROR] Framebuffer incomplete: Draw buffer." << std::endl; + return false; + + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + std::cout << "[ERROR] Framebuffer incomplete: Read buffer." << std::endl; + return false; + + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + std::cout << "[ERROR] Unsupported by FBO implementation." << std::endl; + return false; + + default: + std::cout << "[ERROR] Unknow error." << std::endl; + return false; + } +} + +// std::addressof was introduced in C++11, an equivalent function is defined below +// definition from http://en.cppreference.com/w/cpp/memory/addressof + diff --git a/Source/Processors/Visualization/SpikePlotting/PlotUtils.h b/Source/Processors/Visualization/SpikePlotting/PlotUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..bffdd3c45fe4b63702286a927c6f17843c57b24d --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/PlotUtils.h @@ -0,0 +1,59 @@ +#ifndef PLOT_UTILS_H_ +#define PLOT_UTILS_H_ + +#define GL_GLEXT_PROTOTYPES + +#if defined(__linux__) + #include <GL/glut.h> +#else // assume OS X + #include <GLUT/glut.h> + #include <OpenGL/glu.h> + #include <OpenGL/glext.h> +#endif + +#include <stdio.h> +#include <math.h> +#include <cstring> +#include <iostream> +#include <vector> +#include <FTGL/ftgl.h> + +#include "../../../../JuceLibraryCode/JuceHeader.h" + +#define WAVE1 0 +#define WAVE2 1 +#define WAVE3 2 +#define WAVE4 3 +#define PROJ1x2 4 +#define PROJ1x3 5 +#define PROJ1x4 6 +#define PROJ2x3 7 +#define PROJ2x4 8 +#define PROJ3x4 9 + +void checkGlError(); +void setViewportRange(int xMin,int xMax,int yMin,int yMax); + +void drawString(float x, float y, void *f, const char *string); +void drawString(float x, float y, int size, String s, FTPixmapFont* f); + +void drawViewportEdge(); + +void drawViewportCross(); + +int roundUp(int, int); + +double ad16ToUv(int ad, int gain); + +void makeLabel(int val, int gain, bool convert, char * s); + +void n2ProjIdx(int i, int *p1, int *p2); + +template< class T > +T* addressof(T& arg) { + return (T*)&(char&)arg; +} + +bool isFrameBufferExtensionSupported(); +bool checkFramebufferStatus(); +#endif \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..204f579643386a60053d50bceedc6df80c8afb93 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp @@ -0,0 +1,329 @@ +#include "ProjectionAxes.h" + +ProjectionAxes::ProjectionAxes(): + GenericAxes(), + drawGrid(false), + overlay(false), + convertLabelUnits(true), + buffIdx(-1), + totalSpikes(0), + newSpike(false), + isTextureValid(false), + allSpikesNextRender(false) +{ + GenericAxes::type = PROJ1x2; + GenericAxes::gotFirstSpike = false; + + ylims[0] = 0; + ylims[1] = 1; + setPointColor(1.0,1.0,1.0); + n2ProjIdx(type, &Dim1, &Dim2); + + clearOnNextDraw = false; +} + +ProjectionAxes::ProjectionAxes(int x, int y, double w, double h, int t): + GenericAxes(x,y,w,h,t), + drawGrid(true), + overlay(false), + convertLabelUnits(true), + buffIdx(-1), + totalSpikes(0), + newSpike(false), + isTextureValid(false), + allSpikesNextRender(false) +{ + GenericAxes::gotFirstSpike = false; + + setPointColor(1.0,1.0,1.0); + + n2ProjIdx(type, &Dim1, &Dim2); + + clearOnNextDraw = false; +} + +void ProjectionAxes::updateSpikeData(SpikeObject s){ + //std::cout<<"ProjectionAxes::updateSpikeData()"<<std::endl; + GenericAxes::updateSpikeData(s); + + buffIdx++; + if (buffIdx >= AMP_BUFF_MAX_SIZE) + buffIdx %= AMP_BUFF_MAX_SIZE; + + int idx1, idx2; + calcWaveformPeakIdx(ampDim1,ampDim2,&idx1, &idx2); + + ampBuffer[0][buffIdx] = s.data[idx1]; + ampBuffer[1][buffIdx] = s.data[idx2]; + newSpike = true; +} + +void ProjectionAxes::redraw(){ + + BaseUIElement::redraw(); + + plot(); + + BaseUIElement::drawElementEdges(); +} + + +void ProjectionAxes::plot(){ + //setViewportRange(xlims[0], ylims[0], xlims[1], ylims[1]); + + GLenum errCode; + const GLubyte *errString; + + // Should we plot all spikes to the texture or just the newest one + bool allSpikes = false; + + if (!isTextureValid){ + std::cout<<"ProjectionAxes::plot() --> Texture is invalid regenerating it!"<<std::endl; + createTexture(); + allSpikes = true; + } + + if (clearOnNextDraw){ + clearTexture(); + clearOnNextDraw = false; + } + + drawSpikesToTexture(allSpikes); + drawTexturedQuad(); + plotNewestSpike(); + + // if there has been an openGL error we need to rerender the texture and replot everything + // errors occur when the openGL context has been destroyed and recreated. I'm not sure how to + // explicitly catch that event so instead we check for a drawing error. + if ((errCode = glGetError()) != GL_NO_ERROR) { + errString = gluErrorString(errCode); + std::cout<<"OpenGL Error:"<< errString << "! Invalidating and rerendering the texture!" << std::endl; + + invalidateTexture(); + plot(); + return; + } +} + +void ProjectionAxes::plotOldSpikes(bool allSpikes){ + //std::cout<<"ProjectionAxes::plotOldSpikes() allSpikes:"<<allSpikes<<std::endl; + + //set the viewport to the size of the texture + glViewport(0,0,texWidth, texHeight); + + //set the plotting range for the viewport to the limits of the plot + setViewportRange(xlims[0], ylims[0], xlims[1], ylims[1]); + + // if allSpikes plot start with 1 else start with buffIdx + int startIdx = (allSpikes) ? 1 : buffIdx; + // either plot to totalSpikes or the end of the buffer if total spikes has wrapped + int stopIdx = (totalSpikes > AMP_BUFF_MAX_SIZE) ? AMP_BUFF_MAX_SIZE : buffIdx; + + // if (allSpikes) + // std::cout<<"\tUpdating texture with all spikes: "<< stopIdx - startIdx + 1 <<std::endl; + + glColor3f(1.0, 1.0, 1.0); + glPointSize(1); + glBegin(GL_POINTS); + for (int i=startIdx; i<=stopIdx; i++) + glVertex2i(ampBuffer[0][i], ampBuffer[1][i]); + glEnd(); + +} + + +void ProjectionAxes::plotNewestSpike(){ + + BaseUIElement::setGlViewport(); + setViewportRange(xlims[0], ylims[0], xlims[1], ylims[1]); + + // draw the newest spike as a big red point so it stands out against the old spikes + glColor3f(1.0, 0.0, 0.0); + glPointSize(4); + + glBegin(GL_POINTS); + glVertex2i(ampBuffer[0][buffIdx], ampBuffer[1][buffIdx]); + glEnd(); + + newSpike = false; +} + + void ProjectionAxes::calcWaveformPeakIdx(int d1, int d2, int *idx1, int *idx2){ + + int max1 = -1*pow(2,15); + int max2 = max1; + + for (int i=0; i<s.nSamples ; i++){ + if (s.data[d1*s.nSamples + i] > max1) + { + *idx1 = d1*s.nSamples+i; + max1 = s.data[*idx1]; + } + if (s.data[d2*s.nSamples+i] > max2) + { + *idx2 = d2*s.nSamples+i; + max2 = s.data[*idx2]; + } + } +} + +void ProjectionAxes::setPosition(int x, int y, int w, int h){ + // std::cout<<"ProjectionAxes::setPosition()"<<std::endl; + + // only invalidate the texture if its size has actually changed + if (w!=GenericAxes::width || h!=GenericAxes::height) + invalidateTexture(); + + GenericAxes::setPosition(x,y,w,h); +} + +void ProjectionAxes::setPointColor(GLfloat r, GLfloat g, GLfloat b){ + pointColor[0] = r; + pointColor[1] = g; + pointColor[2] = b; +} +void ProjectionAxes::setGridColor(GLfloat r, GLfloat g, GLfloat b){ + gridColor[0] = r; + gridColor[1] = g; + gridColor[2] = b; +} + + +void ProjectionAxes::createTexture(){ + + texWidth = BaseUIElement::width; + texHeight = BaseUIElement::height; + + std::cout<<"Creating a new texture of size:"<<texWidth<<"x"<<texHeight<<std::endl; + // Delete the old texture + glDeleteTextures(1, &textureId); + // Generate a new texture + glGenTextures(1, &textureId); + // Bind the texture, and set the appropriate parameters + glBindTexture(GL_TEXTURE_2D, textureId); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + // generate a new FrameBufferObject + createFBO(); + + // the texture should now be valid, set the flag appropriately + isTextureValid = true; + +} + +void ProjectionAxes::createFBO(){ + std::cout<<"Creating a new frame buffer object"<<std::endl; + + // if (!isTextureValid) + // createTexture(); + // Delete the old frame buffer, render buffer + glDeleteFramebuffers(1, &fboId); + glDeleteRenderbuffers(1, &rboId); + + // Generate and Bind the frame buffer + glGenFramebuffersEXT(1, &fboId); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId); + + // Generate and bind the new Render Buffer + glGenRenderbuffersEXT(1, &rboId); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texWidth, texHeight); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + + // Attach the texture to the framebuffer + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId); + + // If the FrameBuffer wasn't created then we have a bigger problem. Abort the program. + if(!checkFramebufferStatus()){ + std::cout<<"FrameBufferObject not created! Are you running the newest version of OpenGL?"<<std::endl; + std::cout<<"FrameBufferObjects are REQUIRED! Quitting!"<<std::endl; + exit(1); + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + +void ProjectionAxes::drawSpikesToTexture(bool allSpikes){ + + //std::cout<<"ProjectionAxes::drawSpikesToTexture() plotting all spikes:"<<allSpikes<<std::endl; + + + // For some reason if we want to plot ALL the spikes to a texture we must plot two draw cycles + // in a row, perhaps this has to do with double buffering, i'm not sure why... investigae this! + + // if the allSpikes flag is set we set the allSpikesNextRender as true so we plot next + // all spikes next render cycle too, if only the allSpikesNextRender is true we set all spikes + // to true and allSpikes next render to false. + + //Basically this logic ensures that if allSpikes is ever set to true it will be set to true + //on the next call to drawSpikesToTexture() regardless of what value it is actually set to + if (allSpikes) + allSpikesNextRender = true; + else if (!allSpikes && allSpikesNextRender) + { + allSpikes = true; + allSpikesNextRender = false; + } + // set the rendering destination to FBO + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId); + + // plot to the texture + plotOldSpikes(allSpikes); + + // bind the original FrameBuffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + +void ProjectionAxes::invalidateTexture(){ + isTextureValid = false; +} + + +void ProjectionAxes::drawTexturedQuad(){ + BaseUIElement::setGlViewport(); + // We need to scale the viewport in this case because we want to fill it with a quad. + // if we load identity then we can use a quad bound by (-1, 1); + glLoadIdentity(); + + // Bind the texture to render + glBindTexture(GL_TEXTURE_2D, textureId); + + // Build the quad + int size = 1; + int texS = 1; + glBegin(GL_QUADS); + glColor4f(1, 1, 1, 1); + glTexCoord2f(texS, texS); glVertex3f(size, size,0); + glTexCoord2f(0, texS); glVertex3f(-1 * size , size,0); + glTexCoord2f(0, 0); glVertex3f(-1 * size, -1 * size,0); + glTexCoord2f(texS, 0); glVertex3f(size, -1 * size,0); + glEnd(); + + // Unbind the texture + glBindTexture(GL_TEXTURE_2D, 0); +} + +void ProjectionAxes::clear(){ + + //reset buffIDx and totalSpikes + buffIdx = 0; + totalSpikes = 0; + + // set flag to clear on next draw + clearOnNextDraw = true; +} + +void ProjectionAxes::clearTexture(){ + std::cout<<"ProjectinAxes::clearTexture() --> Clearing the Texture!"<<std::endl; + + glViewport(0,0,texWidth, texHeight); + setViewportRange(xlims[0], ylims[0], xlims[1], ylims[1]); + + // set the rendering destination to FBO + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId); + // Clear the framebufferObject + glClearColor (0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h new file mode 100644 index 0000000000000000000000000000000000000000..f3fdfd0c1b65fc75e6bb76c82ae518449fc86c67 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h @@ -0,0 +1,94 @@ +#ifndef PROJECTION_AXES_H_ +#define PROJECTION_AXES_H_ + +#define GL_GLEXT_PROTOTYPES + +#if defined(__linux__) + #include <GL/glut.h> +#else + #include <GLUT/glut.h> +#endif +#include <stdlib.h> +#include "BaseUIElement.h" +#include "../SpikeObject.h" +#include "PlotUtils.h" +#include "GenericAxes.h" +#include <stdint.h> + +#define AMP_BUFF_MAX_SIZE 50000 + +class ProjectionAxes: public GenericAxes{ + + GLfloat pointColor[3]; + GLfloat gridColor[3]; + + int ampBuffer[2][AMP_BUFF_MAX_SIZE]; + uint16_t buffIdx; // points to the most recent spike + uint64_t totalSpikes; + + + int ampDim1, ampDim2; + + + void drawProjectionGrid(int thold, int gain); + void calcWaveformPeakIdx(int, int, int*, int*); + + void createTexture(); + void createFBO(); + + void drawSpikesToTexture(bool allSpikes); + // void updateTexture(); + void drawTexturedQuad(); + void plotOldSpikes(bool allSpikes); + void plotNewestSpike(); + + bool newSpike; + + + GLuint fboId; // Frame Buffer Object + GLuint textureId; // Texture + GLuint rboId; // Render Buffer + + int texWidth; + int texHeight; + + bool clearOnNextDraw; + bool isTextureValid; + void clearTexture(); + + void validateTexture(); + + bool allSpikesNextRender; + +protected: + void plot(); + + +public: + ProjectionAxes(); + ProjectionAxes(int x, int y, double w, double h, int t); + + void setPosition(int, int, int, int); + void updateSpikeData(SpikeObject s); + + void setPointColor(GLfloat r, GLfloat g, GLfloat b); + void setGridColor(GLfloat, GLfloat, GLfloat); + + void clear(); + void invalidateTexture(); + + void redraw(); + + bool overlay; + bool drawGrid; + bool convertLabelUnits; + + +}; + +#endif // PROJECTION_AXES_H_ + + + + +// #endif diff --git a/Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h b/Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h new file mode 100644 index 0000000000000000000000000000000000000000..1ce4277790e72b9f3d90dca14e4f187011adf23e --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h @@ -0,0 +1,25 @@ +#ifndef SIMPLE_KEY_EVENT_H +#define SIMPLE_KEY_EVENT_H + +struct SimpleKeyEvent{ + + int key; + bool shift; + bool ctrl; + bool alt; +// +// ArteKeyEvent(){ +// key = 0; +// shift = false; +// ctrl = false; +// alt = false; +// } +// ArteKeyEvent(int k){ +// key = k; +// shift = false; +// `ctrl = false; +// alt = false; +// } +}; + +#endif \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8fe109639256817d29504eda70c9a8e403df23d --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp @@ -0,0 +1,193 @@ +#include "StereotrodePlot.h" +#include "../SpikeObject.h" +#include "PlotUtils.h" + +StereotrodePlot::StereotrodePlot(): + BaseUIElement(), limitsChanged(true) +{ + +} + +StereotrodePlot::StereotrodePlot(int x, int y, int w, int h): + BaseUIElement(x,y,w,h,0), limitsChanged(true) +{ + + initAxes(); +} + +StereotrodePlot::~StereotrodePlot(){ +} + +// Each plot needs to update its children axes when its redraw gets called. +// it also needs to call the parent plot when children axes get added it +// should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3 +// should go by default. This isn't as general as it should be but its a good push in +// the right direction + +void StereotrodePlot::redraw(){ + //std::cout<<"StereotrodePlot() starting drawing"<<std::endl;\ + //BaseUIElement::clearNextDraw = true; + //BaseUIElement::redraw(); + + wAxes[0].redraw(); + wAxes[1].redraw(); + pAxes.redraw(); +} + +// This would normally happen for collection of axes but an electrode plot doesn't have a collection instead its a single axes +void StereotrodePlot::processSpikeObject(SpikeObject s){ + //std::cout<<"ElectrdePlot::processSpikeObject()"<<std::endl; + wAxes[0].updateSpikeData(s); + wAxes[1].updateSpikeData(s); + pAxes.updateSpikeData(s); +} + +void StereotrodePlot::setEnabled(bool e){ + BaseUIElement::enabled = e; + + wAxes[0].setEnabled(e); + wAxes[1].setEnabled(e); + pAxes.setEnabled(e); +} + +bool StereotrodePlot::getEnabled(){ + return BaseUIElement::enabled; +} + + +void StereotrodePlot::initAxes(){ + initLimits(); + + int minX = BaseUIElement::xpos; + int minY = BaseUIElement::ypos; + + double axesWidth = BaseUIElement::width/2; + double axesHeight = BaseUIElement::height; + + + wAxes[0] = WaveAxes(minX, minY, axesWidth/2, axesHeight, WAVE1); + wAxes[1] = WaveAxes(minX + axesWidth/2, minY, axesWidth/2, axesHeight, WAVE2); + pAxes = ProjectionAxes(minX + axesWidth, minY, axesWidth, axesHeight, PROJ1x2); + + wAxes[0].setWaveformColor(1.0, 1.0, 1.0); + wAxes[1].setWaveformColor(1.0, 1.0, 1.0); + pAxes.setPointColor(1.0, 1.0, 1.0); + + setLimitsOnAxes(); +} + +void StereotrodePlot::setLimitsOnAxes(){ + std::cout<<"StereotrodePlot::setLimitsOnAxes()"<<std::endl; + + wAxes[0].setYLims(limits[0][0], limits[0][1]); + wAxes[1].setYLims(limits[1][0], limits[1][1]); + pAxes.setYLims(limits[0][0], limits[0][1]); + pAxes.setXLims(limits[1][0], limits[1][1]); + + +} +void StereotrodePlot::setPosition(int x, int y, double w, double h){ + +// std::cout<<"StereotrodePlot::setPosition()"<<std::endl; + BaseUIElement::setPosition(x,y,w,h); + int minX = BaseUIElement::xpos; + int minY = BaseUIElement::ypos; + + double axesWidth = BaseUIElement::width/2; + double axesHeight = BaseUIElement::height; + + wAxes[0].setPosition(minX, minY, axesWidth/2, axesHeight); + wAxes[1].setPosition(minX + axesWidth/2, minY, axesWidth/2, axesHeight); + pAxes.setPosition(minX + axesWidth, minY, axesWidth, axesHeight); +} + +int StereotrodePlot::getNumberOfAxes(){ + return 2; +} + +void StereotrodePlot::initLimits(){ + for (int i=0; i<2; i++) + { + limits[i][0] = -1*pow(2,11); + limits[i][1] = pow(2,14)*1.6; + } + +} + +void StereotrodePlot::getPreferredDimensions(double *w, double *h){ + *w = 75; + *h = 75; +} + +void StereotrodePlot::clear(){ + std::cout<<"StereotrodePlot::clear()"<<std::endl; + pAxes.clear(); +} + + +bool StereotrodePlot::processKeyEvent(SimpleKeyEvent k){ + // std::cout<<"Key:"<<(char)k.key<<std::endl; + // switch(k.key) + // { + // case '=': + // for (int i=0; i<=WAVE4; i++) + // zoomWaveform(i, false, 3); + // break; + // case '+': + // for (int i=0; i<=WAVE4; i++) + // panWaveform(i, false, 3); + // break; + // case '-': + // for (int i=0; i<=WAVE4; i++) + // zoomWaveform(i, false, -3); + // break; + // case '_': + // for (int i=0; i<=WAVE4; i++) + // panWaveform(i, false, -3); + // break; + // case 'C': + // clearOnNextDraw(true); + // break; + // } +} + +void StereotrodePlot::pan(int dim, bool up){ + + std::cout<<"StereotrodePlot::pan() dim:"<<dim<<std::endl; + if (dim>1 || dim<0) + return; + + int mean = (limits[dim][0] + limits[dim][1])/2; + int dLim = limits[dim][1] - mean; + + if (up) + mean = mean + dLim/20; + else + mean = mean - dLim/20; + + limits[dim][0] = mean-dLim; + limits[dim][1] = mean+dLim; + + setLimitsOnAxes(); +} +void StereotrodePlot::zoom(int dim, bool in){ + std::cout<<"StereotrodePlot::zoom()"<<std::endl; + + if (dim>1 || dim<0) + return; + + int mean = (limits[dim][0] + limits[dim][1])/2; + int dLim = limits[dim][1] - mean; + + if (in) + dLim = dLim * .90; + else + dLim = dLim / .90; + + limits[dim][0] = mean-dLim; + limits[dim][1] = mean+dLim; + + setLimitsOnAxes(); +} + + diff --git a/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h new file mode 100644 index 0000000000000000000000000000000000000000..73ce14f5b1287098ac9121062243d95e0c3f059b --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h @@ -0,0 +1,75 @@ +#ifndef STEROETRODE_PLOT_H_ +#define STEROETRODE_PLOT_H_ + +#if defined(__linux__) + #include <GL/glut.h> +#else + #include <GLUT/glut.h> +#endif +#include <list> +#include <math.h> + +#include "WaveAxes.h" +#include "ProjectionAxes.h" +#include "BaseUIElement.h" +#include "PlotUtils.h" +#include "SimpleKeyEvent.h" + + +class StereotrodePlot : public BaseUIElement{ + + bool enabled; + + bool limitsChanged; + double limits[2][2]; + + WaveAxes wAxes[2]; + ProjectionAxes pAxes; + + + + // void zoomAxes(int n, bool xdim, int zoomval); + // void zoomProjection (int n, bool xdim, int zoomval); + // void zoomWaveform (int n, bool xdim, int zoomval); + + // void panAxes(int n, bool xdim, int panval); + // void panProjection (int n, bool xdim, int panval); + // void panWaveform(int n, bool xdim, int panval); + + void initLimits(); + void setLimitsOnAxes(); + + +public: + StereotrodePlot(); + StereotrodePlot(int x, int y,int w,int h); + ~StereotrodePlot(); + + void initAxes(); + void redraw(); + + void setEnabled(bool enabled); + bool getEnabled(); + void setPosition(int,int,double,double); + + void getPreferredDimensions(double*, double*); + + int getNumberOfAxes(); + + void mouseDown(int x, int y); + + void mouseDragX(int dx, bool shift, bool ctr); + void mouseDragY(int dy, bool shift, bool ctr); + + bool processKeyEvent(SimpleKeyEvent k); + + void processSpikeObject(SpikeObject s); + + void clear(); + void zoom(int, bool); + void pan(int, bool); +}; + + + +#endif diff --git a/Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d4c86611874fe4cc17669fc4e6224af8826e529 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp @@ -0,0 +1,320 @@ +#include "TetrodePlot.h" +#include "../SpikeObject.h" +#include "PlotUtils.h" + +TetrodePlot::TetrodePlot(): + BaseUIElement(), limitsChanged(true) +{ +} + +TetrodePlot::TetrodePlot(int x, int y, int w, int h): + BaseUIElement(x,y,w,h,0), limitsChanged(true) +{ + + initAxes(); +} + +TetrodePlot::~TetrodePlot(){ +} + +// Each plot needs to update its children axes when its redraw gets called. +// it also needs to call the parent plot when children axes get added it +// should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3 +// should go by default. This isn't as general as it should be but its a good push in +// the right direction + +void TetrodePlot::redraw(){ + //std::cout<<"TetrodePlot() starting drawing"<<std::endl;\ + BaseUIElement::clearNextDraw = true; + + BaseUIElement::redraw(); + + for (int i=0; i<4; i++) + wAxes[i].redraw(); + + for (int i=0; i<6; i++) + pAxes[i].redraw(); +} + +// This would normally happen for collection of axes but an electrode plot doesn't have a collection instead its a single axes +void TetrodePlot::processSpikeObject(SpikeObject s){ + //std::cout<<"ElectrdePlot::processSpikeObject()"<<std::endl; + for (int i=0; i<4; i++) + wAxes[i].updateSpikeData(s); + for (int i=0; i<6; i++) + pAxes[i].updateSpikeData(s); +} + +void TetrodePlot::setEnabled(bool e){ + BaseUIElement::enabled = e; + for (int i=0; i<4; i++) + wAxes[i].setEnabled(e); + for (int i=0; i<6; i++) + pAxes[i].setEnabled(e); +} + +bool TetrodePlot::getEnabled(){ + return BaseUIElement::enabled; +} + + +void TetrodePlot::initAxes(){ + initLimits(); + + int minX = BaseUIElement::xpos; + int minY = BaseUIElement::ypos; + + int axesWidth = BaseUIElement::width/4; + int axesHeight = BaseUIElement::height/2; + + + wAxes[0] = WaveAxes(minX, minY, axesWidth/2, axesHeight, WAVE1); + wAxes[1] = WaveAxes(minX + axesWidth/2, minY, axesWidth/2, axesHeight, WAVE2); + wAxes[2] = WaveAxes(minX, minY + axesHeight, axesWidth/2, axesHeight, WAVE3); + wAxes[3] = WaveAxes(minX + axesWidth/2, minY + axesHeight, axesWidth/2, axesHeight, WAVE4); + + // for (int i=0; i<6; i++) + // { + // pAxes[i] = ProjectionAxes( + // minX + axesWidth * ((i%3)+1), + // minY + (i/3) * axesHeight, + // axesWidth , + // axesHeight, + // i); + //} + // + + // because the width of the plot doesn't always divide evenly into 4 we are going to pad the width + // of the 3rd and 6th projection plot to cover up the space cleared by the TetrodePlotElement + + int xPad = 1; + pAxes[0] = ProjectionAxes(minX + axesWidth*1, minY, axesWidth, axesHeight, PROJ1x2); + pAxes[1] = ProjectionAxes(minX + axesWidth*2, minY, axesWidth, axesHeight, PROJ1x3); + pAxes[2] = ProjectionAxes(minX + axesWidth*3, minY, axesWidth+xPad, axesHeight, PROJ1x4); + pAxes[3] = ProjectionAxes(minX + axesWidth*1, minY + axesHeight, axesWidth, axesHeight, PROJ2x3); + pAxes[4] = ProjectionAxes(minX + axesWidth*2, minY + axesHeight, axesWidth, axesHeight, PROJ2x4); + pAxes[5] = ProjectionAxes(minX + axesWidth*3, minY + axesHeight, axesWidth+xPad, axesHeight, PROJ3x4); + + + //axes.setEnabled(false); + for (int i=0; i<4; i++){ + wAxes[i].setYLims(-1*pow(2,11), pow(2,14)*1.6); + wAxes[i].setWaveformColor(1.0, 1.0, 1.0); + } + for (int i=0; i<6; i++) + { + pAxes[i].setXLims(-1*pow(2,11), pow(2,14)*1.6); + pAxes[i].setYLims(-1*pow(2,11), pow(2,14)*1.6); + pAxes[i].setPointColor(1.0, 1.0, 1.0); + } + +} + +void TetrodePlot::setPosition(int x, int y, double w, double h){ + BaseUIElement::setPosition(x,y,w,h); + int minX = BaseUIElement::xpos; + int minY = BaseUIElement::ypos; + + int axesWidth = BaseUIElement::width/4; + int axesHeight = BaseUIElement::height/2; + + wAxes[0].setPosition(minX, minY, axesWidth/2, axesHeight); + wAxes[1].setPosition(minX + axesWidth/2, minY, axesWidth/2, axesHeight); + wAxes[2].setPosition(minX, minY + axesHeight, axesWidth/2, axesHeight); + wAxes[3].setPosition(minX + axesWidth/2, minY + axesHeight, axesWidth/2, axesHeight); + + // pAxes[0].setPosition(minX + axesWidth*1, minY, axesWidth, axesHeight); + // pAxes[1].setPosition(minX + axesWidth*2, minY, axesWidth, axesHeight); + // pAxes[2].setPosition(minX + axesWidth*3, minY, axesWidth, axesHeight); + // pAxes[3].setPosition(minX + axesWidth*1, minY + axesHeight, axesWidth, axesHeight); + // pAxes[4].setPosition(minX + axesWidth*2, minY + axesHeight, axesWidth, axesHeight); + // pAxes[5].setPosition(minX + axesWidth*3, minY + axesHeight, axesWidth, axesHeight); + + //titleBox.setPosition(x, y+h-titleHeight-3, w, titleHeight+3); +} + +void TetrodePlot::setPosition(int x, int y){ + setPosition(x,y, BaseUIElement::width, BaseUIElement::height ); +} + +void TetrodePlot::setDimensions(double w, double h){ + setPosition(BaseUIElement::xpos, BaseUIElement::ypos, w, h); +} + +int TetrodePlot::getNumberOfAxes(){ + return 1;; +} + + +void TetrodePlot::initLimits(){ + for (int i=0; i<4; i++) + { + limits[i][0] = -1*pow(2,11); + limits[i][1] = pow(2,14); + } + +} + +void TetrodePlot::getPreferredDimensions(double *w, double *h){ + *w = 75; + *h = 75; +} +// void TetrodePlot::mouseDown(int x, int y){ + +// // selectedAxesN = -1; +// // std::list<GenericAxes>::iterator i; +// // int idx=-1; +// // bool hit = false; + +// // selectedAxes = NULL; +// // for (i=axesList.begin(); i!=axesList.end(); ++i) +// // { +// // if (i->hitTest(x,y)) +// // { +// // selectedAxes = addressof(*i); +// // selectedAxesN = i->getType(); +// // hit = true; +// // // break; +// // } +// // idx++; +// // } +// // if (!hit) +// // selectedAxes = NULL; +// // if (selectedAxes != NULL) +// // std::cout<<"TetrodePlot::mouseDown() hit:"<<selectedAxes<<" AxesType:"<<selectedaxes.getType()<<std::endl; +// // else +// // std::cout<<"TetrodePlot::mouseDown() NO HIT!"<<std::endl; + +// } +// void TetrodePlot::mouseDragX(int dx, bool shift, bool ctrl){ + +// // if (selectedAxes == NULL || dx==0) +// // return; +// // // zoomAxes(selectedaxes.getType(), true, dx>0); +// // if (shift) +// // zoomAxes(selectedAxesN, true, dx); +// // if (ctrl) +// // panAxes(selectedAxesN, true, dx); + +// } +// void TetrodePlot::mouseDragY(int dy, bool shift, bool ctrl){ +// if (selectedAxes == NULL || dy==0) +// return; +// if(shift) +// zoomAxes(selectedAxesN, false, dy); +// if(ctrl) +// panAxes(selectedAxesN, false, dy); +// } + +// void TetrodePlot::zoomAxes(int n, bool xdim, int zoom){ +// // std::cout<<"TetrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl; +// // If trying to zoom an invalid axes type +// if (n<WAVE1 || n>PROJ3x4) +// return; +// if (n<=WAVE4) +// zoomWaveform(n, xdim, zoom); +// else +// zoomProjection(n, xdim, zoom); +// } + +// void TetrodePlot::zoomWaveform(int n, bool xdim, int zoom){ + +// // waveform plots don't have a xlimits +// if (xdim) +// return; +// // std::cout<<"Zooming Waveform:"<<n<<" zoomin:"<<zoomin<<" "; +// double min, max; + +// if(xdim) +// return; + +// min = limits[n][0]; +// max = limits[n][1]; + +// double mean = (max + min)/2.0f; +// double delta = max - mean; +// delta = delta / pow(.99, -1*zoom); + +// min = mean - delta; +// max = mean + delta; + +// limits[n][0] = min; +// limits[n][1] = max; + +// limitsChanged = true; +// } + +// void TetrodePlot::panAxes(int n, bool xdim, int panval){ +// // std::cout<<"TetrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl; +// // If trying to zoom an invalid axes type +// if (n<WAVE1 || n>PROJ3x4) +// return; +// if (n<=WAVE4) +// panWaveform(n, xdim, panval); +// else +// panProjection(n, xdim, panval); +// } + +// void TetrodePlot::panWaveform(int n, bool xdim, int pan){ + +// // waveform plots don't have a xlimits +// if (xdim) +// return; +// // std::cout<<"Panning Waveform:"<<n<<" pan:"<<pan<<" "<<std::endl; +// double min, max; + +// if(xdim) +// return; + +// min = limits[n][0]; +// max = limits[n][1]; + +// double dy = max-min; + +// // Need to grab something if pan event is driven by the keyboard, which means that all the plots are getting panned so this should be okay +// if (selectedAxes == NULL) +// selectedAxes = &axesList.front(); + +// double yPixels = (BaseUIElement::height - titleHeight)/2.0; + +// double pixelWidth = -1 * dy/yPixels; + +// double delta = pan * pixelWidth; +// min = min + delta; +// max = max + delta; + +// limits[n][0] = min; +// limits[n][1] = max; + +// limitsChanged = true; +// } + + + +bool TetrodePlot::processKeyEvent(SimpleKeyEvent k){ + // std::cout<<"Key:"<<(char)k.key<<std::endl; + // switch(k.key) + // { + // case '=': + // for (int i=0; i<=WAVE4; i++) + // zoomWaveform(i, false, 3); + // break; + // case '+': + // for (int i=0; i<=WAVE4; i++) + // panWaveform(i, false, 3); + // break; + // case '-': + // for (int i=0; i<=WAVE4; i++) + // zoomWaveform(i, false, -3); + // break; + // case '_': + // for (int i=0; i<=WAVE4; i++) + // panWaveform(i, false, -3); + // break; + // case 'C': + // clearOnNextDraw(true); + // break; + // } +} + + diff --git a/Source/Processors/Visualization/SpikePlotting/TetrodePlot.h b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.h new file mode 100644 index 0000000000000000000000000000000000000000..5eaac34babc43fe918010ed8736628286cb2e58d --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.h @@ -0,0 +1,71 @@ +#ifndef TETRODE_PLOT_H_ +#define TETRODE_PLOT_H_ + +#if defined(__linux__) + #include <GL/glut.h> +#else + #include <GLUT/glut.h> +#endif +#include <list> +#include <math.h> + +#include "WaveAxes.h" +#include "ProjectionAxes.h" +#include "BaseUIElement.h" +#include "PlotUtils.h" +#include "SimpleKeyEvent.h" + + +class TetrodePlot : public BaseUIElement{ + + + bool enabled; + + + bool limitsChanged; + double limits[1][2]; + + WaveAxes wAxes[4]; + ProjectionAxes pAxes[6]; + + // void zoomAxes(int n, bool xdim, int zoomval); + // void zoomProjection (int n, bool xdim, int zoomval); + // void zoomWaveform (int n, bool xdim, int zoomval); + + // void panAxes(int n, bool xdim, int panval); + // void panProjection (int n, bool xdim, int panval); + // void panWaveform(int n, bool xdim, int panval); + + void initLimits(); + +public: + TetrodePlot(); + TetrodePlot(int x, int y,int w,int h); + ~TetrodePlot(); + + void initAxes(); + void redraw(); + void setEnabled(bool enabled); + bool getEnabled(); + + void setPosition(int,int,double,double); + void setPosition(int, int); + void setDimensions(double,double); + + void getPreferredDimensions(double*, double*); + + int getNumberOfAxes(); + + void mouseDown(int x, int y); + + void mouseDragX(int dx, bool shift, bool ctr); + void mouseDragY(int dy, bool shift, bool ctr); + + bool processKeyEvent(SimpleKeyEvent k); + + void processSpikeObject(SpikeObject s); +}; + + + +#endif diff --git a/Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp b/Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18feacbed932645bcdf1d36a0a63ea031f7f7347 --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp @@ -0,0 +1,208 @@ +#include "WaveAxes.h" + +WaveAxes::WaveAxes(): + GenericAxes(), + drawWaveformLine(true), + drawWaveformPoints(false), + drawGrid(true), + overlay(false), + convertLabelUnits(true) +{ + GenericAxes::gotFirstSpike = false; + + ylims[0] = 0; + ylims[1] = 1; + setWaveformColor(1.0,1.0,0.6); + setThresholdColor(1.0, 0.1, 0.1); + setGridColor(0.4, 0.2, 0.2); + +} + +WaveAxes::WaveAxes(int x, int y, double w, double h, int t): + GenericAxes(x,y,w,h,t), + drawWaveformLine(true), + drawWaveformPoints(false), + drawGrid(true), + overlay(false), + convertLabelUnits(true) +{ + GenericAxes::gotFirstSpike = false; + + setWaveformColor(1.0,1.0,0.6); + setThresholdColor(1.0, 0.1, 0.1); + setGridColor(0.2, 0.2, 0.2); + +} + +void WaveAxes::updateSpikeData(SpikeObject newSpike){ + //std::cout<<"WaveAxes::updateSpikeData()"<<std::endl; + GenericAxes::updateSpikeData(newSpike); + +} + +void WaveAxes::redraw(){ + + BaseUIElement::redraw(); + + plot(); + + BaseUIElement::drawElementEdges(); +} + + +void WaveAxes::plot(){ + + int chan = 0; + + // If no spikes have been received then don't plot anything + if (!gotFirstSpike) + { + std::cout<<"\tWaiting for the first spike"<<std::endl; + return; + } + + // Set the plotting range for the current axes the xlims member is ignored as the xdims are 0->number of samples per waveform minus one + // so the line goes all the way to the edges ydims are specified by the ylims vector + setViewportRange(0, ylims[0], s.nSamples-1, ylims[1]); + + // draw the grid lines for the waveforms? + if(drawGrid) + drawWaveformGrid(s.threshold[chan], s.gain[chan]); + + //compute the spatial width for each wawveform sample + float dx = 1; + float x = 0; + + // type corresponds to channel so we need to calculate the starting + // sample based upon which channel is getting plotted + // type values are defined in PlotUtils.h + int sampIdx = s.nSamples * type; // + //std::cout<<"Starting with idx:"<<sampIdx<<std::endl; + + + //Draw the individual waveform points connected with a line + glColor3fv(waveColor); + glLineWidth(1); + glBegin( GL_LINE_STRIP ); + + int dSamples = 1; + for (int i=0; i<s.nSamples; i++) + { + //std::cout<<"\t"<<s.data[sampIdx]; + glVertex2f(x, s.data[sampIdx]); + sampIdx += dSamples; + x +=dx; + } + + glEnd(); + + + //Draw the threshold line and label + glColor3fv(thresholdColor); + glLineWidth(1); + glLineStipple(4, 0xAAAA); // make a dashed line + glEnable(GL_LINE_STIPPLE); + + glBegin( GL_LINE_STRIP ); + glVertex2f(0, s.threshold[chan]); + glVertex2f(s.nSamples, s.threshold[chan]); + glEnd(); + + glDisable(GL_LINE_STIPPLE); + + char cstr[100] = {0}; + + makeLabel(s.threshold[chan], s.gain[chan], convertLabelUnits, cstr); + String str = String(cstr); + + float yOffset = (ylims[1] - ylims[0])/BaseUIElement::height * 2; + drawString(1 ,s.threshold[chan] + yOffset, 15, str, font); +} + +void WaveAxes::drawWaveformGrid(int thold, int gain){ + + double voltRange = ylims[1] - ylims[0]; + double pixelRange = BaseUIElement::height; + //This is a totally arbitrary value that seemed to lok the best for me + int minPixelsPerTick = 25; + int MAX_N_TICKS = 10; + + int nTicks = pixelRange / minPixelsPerTick; + while(nTicks>MAX_N_TICKS){ + minPixelsPerTick += 5; + nTicks = pixelRange / minPixelsPerTick; + } + + int voltPerTick = (voltRange / nTicks); + + double meanRange = voltRange/2; + glColor3fv(gridColor); + + glLineWidth(1); + char cstr[200] = {0}; + String str; + + double tickVoltage = thold; + + // If the limits are bad we don't want to hang the program trying to draw too many ticks + // so count the number of ticks drawn and kill the routine after 100 draws + int tickCount=0; + while(tickVoltage < ylims[1] - voltPerTick*1.5) // Draw the ticks above the thold line + { + tickVoltage = roundUp(tickVoltage + voltPerTick, 100); + + glBegin(GL_LINE_STRIP); + glVertex2i(0, tickVoltage); + glVertex2i(s.nSamples, tickVoltage); + glEnd(); + + makeLabel(tickVoltage, gain, convertLabelUnits, cstr); + str = String(cstr); + drawString(1, tickVoltage+voltPerTick/10, 15, str, font); + + if (tickCount++>100) + return; + } + + tickVoltage = thold; + tickCount = 0; + while(tickVoltage > ylims[0] + voltPerTick) // draw the ticks below the thold line + { + tickVoltage = roundUp(tickVoltage - voltPerTick, 100); + + glBegin(GL_LINE_STRIP); + glVertex2i(0, tickVoltage); + glVertex2i(s.nSamples, tickVoltage); + glEnd(); + + makeLabel(tickVoltage, gain, convertLabelUnits, cstr); + str = String(cstr); + drawString(1, tickVoltage+voltPerTick/10, 15, str, font); + + if (tickCount++>100) + return; + } + + +} + +void WaveAxes::setWaveformColor(GLfloat r, GLfloat g, GLfloat b){ + waveColor[0] = r; + waveColor[1] = g; + waveColor[2] = b; +} +void WaveAxes::setThresholdColor(GLfloat r, GLfloat g, GLfloat b){ + thresholdColor[0] = r; + thresholdColor[1] = g; + thresholdColor[2] = b; +} +// void WaveAxes::setPointColor(GLfloat r, GLfloat g, GLfloat b){ +// pointColor[0] = r; +// pointColor[1] = g; +// pointColor[2] = b; +// } +void WaveAxes::setGridColor(GLfloat r, GLfloat g, GLfloat b){ + gridColor[0] = r; + gridColor[1] = g; + gridColor[2] = b; +} \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikePlotting/WaveAxes.h b/Source/Processors/Visualization/SpikePlotting/WaveAxes.h new file mode 100644 index 0000000000000000000000000000000000000000..56add88d8301374fe07b5dd0aa74388a117dd8cb --- /dev/null +++ b/Source/Processors/Visualization/SpikePlotting/WaveAxes.h @@ -0,0 +1,51 @@ +#ifndef WAVE_AXES_H +#define WAVE_AXES_H + +#if defined(__linux__) + #include <GL/glut.h> +#else + #include <GLUT/glut.h> +#endif +#include <stdlib.h> +#include "BaseUIElement.h" +#include "../SpikeObject.h" +#include "PlotUtils.h" +#include "GenericAxes.h" + + +class WaveAxes: public GenericAxes{ + + GLfloat waveColor[3]; + GLfloat thresholdColor[3]; + GLfloat gridColor[3]; + + + void drawWaveformGrid(int thold, int gain); + +protected: + void plot(); + + +public: + WaveAxes(); + WaveAxes(int x, int y, double w, double h, int t); + + void updateSpikeData(SpikeObject s); + + void setWaveformColor(GLfloat r, GLfloat g, GLfloat b); + void setThresholdColor(GLfloat r, GLfloat g, GLfloat b); + void setGridColor(GLfloat, GLfloat, GLfloat); + + void redraw(); + + bool drawWaveformLine; + bool drawWaveformPoints; + bool overlay; + bool drawGrid; + bool convertLabelUnits; + +}; + + + +#endif diff --git a/Source/Processors/Visualization/SpikeViewer.cpp b/Source/Processors/Visualization/SpikeViewer.cpp deleted file mode 100644 index 3a06ca5fbad429b493c3a2473f4e0c6b0e864677..0000000000000000000000000000000000000000 --- a/Source/Processors/Visualization/SpikeViewer.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2012 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "SpikeViewer.h" - - -SpikeViewer::SpikeViewer(AudioSampleBuffer* sBuffer, MidiBuffer* eBuffer, UIComponent* ui) - : Renderer(sBuffer, eBuffer, ui) -{ - -} - - - -SpikeViewer::~SpikeViewer() {} - -void SpikeViewer::resized() -{ - - xBox = getWidth()/4; - yBox = getHeight()/2; - yPadding = 5; - xPadding = 5; - - glClear(GL_COLOR_BUFFER_BIT); - - clearWaveforms(); - clearProjections(); - -} - -void SpikeViewer::newOpenGLContextCreated() -{ - - glClearDepth (1.0); - - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - glOrtho(0, 1, 1, 0, 0, 1); - glMatrixMode (GL_MODELVIEW); - - glClearColor(0.2f, 0.2f, 0.2f, 1.0f); - - resized(); - - glFlush(); - -} - -void SpikeViewer::clearWaveforms() -{ - - for (int n = 0; n < 4; n++) - { - setViewportForWaveN(n); - drawBorder(); - } - -} - -void SpikeViewer::clearProjections() -{ - for (int n = 0; n < 6; n++) - { - setViewportForProjectionN(n); - drawBorder(); - } - -} - -void SpikeViewer::renderOpenGL() -{ - - if (eventBuffer->getNumEvents() > 0) { - - glRasterPos2f(0.1,0.1); - - //const char* str = "i"; - // void* font = GLUT_BITMAP_8_BY_13; - - // glutBitmapCharacter(font,54); - // drawBorder(); - - //std::cout << "Events received by Spike Viewer." << std::endl; - - MidiBuffer::Iterator i (*eventBuffer); - MidiMessage message(0xf4); - - int samplePosition; - i.setNextSamplePosition(samplePosition); - - //Array<int> peaks; - - - clearWaveforms(); - - while (i.getNextEvent (message, samplePosition)) { - - int numbytes = message.getRawDataSize(); - int numSamples = (numbytes-2)/2; - uint8* dataptr = message.getRawData(); - - int chan = (*dataptr<<8) + *(dataptr+1); - int electrode = config->getSource(0)->getElectrodeNumberForChannel(chan); - - //std::cout << chan << "::" << electrode << std::endl; - - dataptr += 2; - - //glViewport(0,0,getWidth()/2,getHeight()); - - if (electrode == 0) - { - //for (int n = 0; n < 4; n++) { - setViewportForWaveN(chan); - float peak = drawWaveform(dataptr, numSamples); - - peaks.set(chan,peak*1.25); - //peaks.set(chan,peak); - - } - - if (peaks.size() == 4) - { - drawProjections(); - peaks.clear(); - } - - //std::cout << " Bytes received: " << numbytes << std::endl; - //std::cout << " Message timestamp = " << message.getTimeStamp() << std::endl; - //std::cout << " Message channel: " << chan << std::endl; - - //std::cout << " "; - - //AudioDataConverters::convertInt16BEToFloat ( dataptr, // source - // spikeData, // dest - // numSamples, // numSamples - // 2 ); // destBytesPerSample = 2 - - //for (int n = 0; n < numSamples; n++) { - // std::cout << String(spikeData[n]) << " "; - //} - - //std::cout << std::endl << std::endl; - } - - // for (int ch = 0; ch < 4; ch++) - // { - - // } - - //eventBuffer->clear(); - - } - - //glOrtho(0, 0.5, 0.5, 0, 0, 1); - glFlush(); - -} - -void SpikeViewer::drawProjections() -{ - - for (int i = 0; i < 6; i++) - { - setViewportForProjectionN(i); - - int d1,d2; - - if (i == 0){ - d1 = 0; - d2 = 1; - } else if (i == 1) { - d1 = 0; - d2 = 2; - } else if (i == 2) { - d1 = 0; - d2 = 3; - } else if (i == 3) { - d1 = 1; - d2 = 2; - } else if (i == 4) { - d1 = 1; - d2 = 3; - } else if (i == 5) { - d1 = 2; - d2 = 3; - } - - glColor3f(0.0, 0.0, 0.0); - glBegin(GL_POINTS); - glVertex2f(1-peaks[d1],peaks[d2]); - glEnd(); - - } - -} - -float SpikeViewer::drawWaveform(uint8* dataptr, int numSamples) -{ - - glColor3f(0,0.0,0); - - glBegin(GL_LINE_STRIP); - - float maxVal = 0; - - for (int n = 0; n < numSamples; n++) - { - uint16 sampleValue = (*dataptr << 8) + *(dataptr+1); - - float sampleVal = -float(sampleValue - 32768)/32768 + 0.6; - - (sampleVal > maxVal) ? maxVal = sampleVal : maxVal = maxVal; - - glVertex2f(float(n)/numSamples + 0.01, - sampleVal); - dataptr += 2; - - } - - glEnd(); - - return maxVal; - -} - -void SpikeViewer::drawBorder() -{ - - glColor3f(0.9,0.7,0.2); - - glRectf(0.01f,0.01f,0.99f,0.99f); - - // glBegin(GL_LINE_STRIP); - // glVertex2f(0.01f, 0.01f); - // glVertex2f(0.99f, 0.01f); - // glVertex2f(0.99f, 0.99f); - // glVertex2f(0.01f, 0.99f); - // glVertex2f(0.01f, 0.01f); - // glEnd(); -} - -void SpikeViewer::setViewportForProjectionN(int n) -{ - // std::cout<<"Setting viewport on projection:"<<n<<std::endl; - float viewDX = xBox; - float viewDY = yBox; - float viewX,viewY; - - switch (n){ - case 0: - viewX=xBox; - viewY=yBox; - break; - case 1: - viewX = xBox*2; - viewY = yBox; - break; - case 2: - viewX=xBox*3; - viewY=yBox; - break; - case 3: - viewX = xBox; - viewY = 0; - break; - case 4: - viewX = xBox*2; - viewY = 0; - break; - case 5: - viewX = xBox*3; - viewY = 0; - break; - default: - std::cout<<"drawing of more than 4 channels is not supported, returning! Requested:"<<n<<std::endl; - return; - } - viewX = viewX + xPadding; - viewY = viewY + yPadding; - viewDX = viewDX - 2*xPadding; - viewDY = viewDY - 2*yPadding; - - glViewport(viewX, viewY, viewDX, viewDY); - -} - - -void SpikeViewer::setViewportForWaveN(int n){ - float viewDX = xBox/2; - float viewDY = yBox; - float viewX,viewY; - switch (n){ - case 0: - viewX=0; - viewY=yBox; - break; - case 1: - viewX = xBox/2; - viewY = yBox; - break; - case 2: - viewX=0; - viewY=0; - break; - case 3: - viewX = xBox/2; - viewY = 0; - break; - default: - std::cout<<"drawing of more than 4 channels is not supported, returning! Requested:"<<n<<std::endl; - return; - } - viewX = viewX + xPadding; - viewY = viewY + yPadding; - viewDX = viewDX - 2*xPadding; - viewDY = viewDY - 2*yPadding; - glViewport(viewX,viewY,viewDX,viewDY); -} \ No newline at end of file diff --git a/Source/Processors/Visualization/SpikeViewer.h b/Source/Processors/Visualization/SpikeViewer.h deleted file mode 100644 index 0ab44684ebe17560d4fdd25ed7d3edfff4c4705c..0000000000000000000000000000000000000000 --- a/Source/Processors/Visualization/SpikeViewer.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2012 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef __SPIKEVIEWER_H_AF442416__ -#define __SPIKEVIEWER_H_AF442416__ - -#include "../../../JuceLibraryCode/JuceHeader.h" -#include "../Editors/Visualizer.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -#if JUCE_WINDOWS -#include <gl/gl.h> -#include <gl/glu.h> -#elif JUCE_LINUX -#include <GL/gl.h> -#include <GL/glut.h> -#undef KeyPress -#elif JUCE_IPHONE -#include <OpenGLES/ES1/gl.h> -#include <OpenGLES/ES1/glext.h> -#elif JUCE_MAC -#include <GLUT/glut.h> -#endif - -#ifndef GL_BGRA_EXT -#define GL_BGRA_EXT 0x80e1 -#endif - -/** - - --THIS FILE IS OBSOLETE, BUT REMAINS FOR REFERENCE PURPOSES-- - -*/ - - -class SpikeViewer : public Renderer -{ -public: - SpikeViewer(AudioSampleBuffer* streamBuffer, MidiBuffer* eventBuffer, UIComponent* ui); - ~SpikeViewer(); - void renderOpenGL(); - void newOpenGLContextCreated(); - - //void setViewportForProjection -private: - int nTrodes; - - Array<float> peaks; - - float xBox, yBox, xPadding, yPadding; - - void drawBorder(); - - void clearWaveforms(); - void clearProjections(); - - void drawProjections(); - float drawWaveform(uint8* dataptr, int numSamples); - - void setViewportForWaveN(int n); - void setViewportForProjectionN(int n); - - void resized(); - -}; - - -#endif // __SPIKEVIEWER_H_AF442416__ diff --git a/Source/UI/Configuration.cpp b/Source/Processors/Visualization/Visualizer.h similarity index 53% rename from Source/UI/Configuration.cpp rename to Source/Processors/Visualization/Visualizer.h index 33bfd6ab625f3ee89ba880b9fe8cc0ab644d65d1..e2832cac0bcffe38cb7cde3f6eed544c16b112f4 100644 --- a/Source/UI/Configuration.cpp +++ b/Source/Processors/Visualization/Visualizer.h @@ -21,45 +21,34 @@ */ -#include "Configuration.h" +#ifndef __VISUALIZER_H_C5943EC1__ +#define __VISUALIZER_H_C5943EC1__ +#include "../../../JuceLibraryCode/JuceHeader.h" +#include "OpenGLCanvas.h" -DataSource::DataSource(GenericProcessor* p, Configuration* c) -{ - - processor = p; - - name = p->getName(); - id = p->getNodeId(); - - firstChan = 0; +class Visualizer : public OpenGLCanvas - for (int n = 0; n < c->numDataSources(); n++) - { - firstChan += c->getSource(n)->getNumChans(); - } - - numChans = p->getNumOutputs(); +{ +public: + Visualizer() {} + ~Visualizer() {} - nextAvailableChan = firstChan; + virtual void newOpenGLContextCreated() = 0; + virtual void renderOpenGL() = 0; - channelMapping.ensureStorageAllocated(numChans); + virtual void refreshState() = 0; - totalElectrodes = 0; + virtual void update() = 0; + virtual int getTotalHeight() = 0; -} + virtual void beginAnimation() = 0; + virtual void endAnimation() = 0; + virtual void setParameter(int, float) = 0; + virtual void setParameter(int, int, int, float) = 0; -void Configuration::removeDataSource(GenericProcessor* p) -{ - std::cout << "Removing data source from configuration!" << std::endl; +}; - for (int n = 0; n < numDataSources(); n++) - { - GenericProcessor* gp = (GenericProcessor*) getSource(n)->getProcessor(); - - if (gp == p) - dataSources.remove(n); - } -} \ No newline at end of file +#endif // __VISUALIZER_H_C5943EC1__ diff --git a/Source/Processors/WiFiOutput.cpp b/Source/Processors/WiFiOutput.cpp index d9fa1ba3f49100e35f0e92a7be6aec5532e13847..ccf3deea3131813cc3459ec867f4fd0de3191024 100644 --- a/Source/Processors/WiFiOutput.cpp +++ b/Source/Processors/WiFiOutput.cpp @@ -27,11 +27,6 @@ WiFiOutput::WiFiOutput() : GenericProcessor("WiFi Output") { - setNumOutputs(0); - setNumInputs(0); - - setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128); - } WiFiOutput::~WiFiOutput() @@ -41,13 +36,8 @@ WiFiOutput::~WiFiOutput() AudioProcessorEditor* WiFiOutput::createEditor() { - WiFiOutputEditor* wifiEditor = new WiFiOutputEditor(this); - - setEditor(wifiEditor); - //wifiEditor->setConfiguration(config); - - std::cout << "Creating editor." << std::endl; - return wifiEditor; + editor = new WiFiOutputEditor(this); + return editor; } @@ -57,12 +47,12 @@ void WiFiOutput::setParameter (int parameterIndex, float newValue) } void WiFiOutput::process(AudioSampleBuffer &buffer, - MidiBuffer &midiMessages, + MidiBuffer &events, int& nSamples) { - int sampleNum = checkForMidiEvents(midiMessages); + int sampleNum = checkForEvents(events); if (sampleNum >= 0) { diff --git a/Source/UI/Configuration.h b/Source/UI/Configuration.h deleted file mode 100644 index 9a24edea1585112bb739a278488fe6852d3ebefd..0000000000000000000000000000000000000000 --- a/Source/UI/Configuration.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2012 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef __CONFIGURATION_H_9DEA9372__ -#define __CONFIGURATION_H_9DEA9372__ - -#include "../../JuceLibraryCode/JuceHeader.h" -#include "../Processors/GenericProcessor.h" - -/** - - Holds configuration information for the signal chain. - - The Configuration can be accessed by all processors in order to - update channel names, electrode groupings, and acquisition parameters. - - @see UIComponent, GenericProcessor - -*/ - -class GenericProcessor; -class Configuration; - -class Trode -{ -public: - Trode(int nchans, int startChan, String name_) - { - name = name_; - - for (int n = 0; n < nchans; n++) - { - channelMapping.add(startChan++); - inputRange.add(10000.0); - threshold.add(5000.0); - isActive.add(true); - } - } - - ~Trode() {} - - int numChannels() {return channelMapping.size();} - - void setChannel(int wire, int chan) - { - if (checkWire(wire)) - channelMapping.set(wire,chan); - } - - void setThreshold(int wire, float thresh) - { - if (checkWire(wire)) - threshold.set(wire,thresh); - } - - void setInputRange(int wire, float inRange) - { - if (checkWire(wire)) - inputRange.set(wire,inRange); - } - - void setState(int wire, bool state) - { - if (checkWire(wire)) - isActive.set(wire,state); - } - - int getChannel(int wire) - { - if (checkWire(wire)) - return channelMapping[wire]; - else - return -1; - } - - float getThreshold(int wire) - { - if (checkWire(wire)) - return threshold[wire]; - else - return -1; - } - - float getInputRange(int wire) - { - if (checkWire(wire)) - return inputRange[wire]; - else - return -1; - } - - bool getState(int wire) - { - if (checkWire(wire)) - return isActive[wire]; - else - return false; - } - - int* getRawDataPointer() - { - return channelMapping.getRawDataPointer(); - } - - String getName() {return name;} - -private: - Array<int, CriticalSection> channelMapping; - Array<float, CriticalSection> threshold; - Array<float, CriticalSection> inputRange; - Array<bool, CriticalSection> isActive; - - String name; - - bool checkWire(int wire) - { - if (wire < channelMapping.size() && wire > -1) - return true; - else - return false; - } - -}; - -class DataSource -{ -public: - DataSource(GenericProcessor* p, Configuration* c); - - ~DataSource() {} - - GenericProcessor* getProcessor() {return processor;} - - int numTetrodes() {return tetrodes.size();} - int numStereotrodes() {return stereotrodes.size();} - int numSingleWires() {return singleWires.size();} - int getElectrodeNumberForChannel(int chan) - { - return channelMapping[chan]; - } - - Trode* getTetrode(int n) {return tetrodes[n];} - Trode* getStereotrode(int n) {return stereotrodes[n];} - Trode* getSingleWire(int n) {return singleWires[n];} - - void addTrode(int numChannels, String name_) - { - Trode* t = new Trode(numChannels, nextAvailableChan, name_); - - for (int n = 0; n < numChannels; n++) - { - channelMapping.set(nextAvailableChan++, totalElectrodes); - } - - totalElectrodes++; - - if (t->numChannels() == 1) - singleWires.add(t); - else if (t->numChannels() == 2) - stereotrodes.add(t); - else if (t->numChannels() == 4) - tetrodes.add(t); - } - - String getName() {return name;} - - int getNumChans() {return numChans;} - int getFirstChan() {return firstChan;} - - int id; - -private: - - String name; - - OwnedArray<Trode, CriticalSection> tetrodes; - OwnedArray<Trode, CriticalSection> stereotrodes; - OwnedArray<Trode, CriticalSection> singleWires; - Array<int, CriticalSection> channelMapping; - - int totalElectrodes; - int firstChan; - int numChans; - int nextAvailableChan; - - GenericProcessor* processor; - -}; - -class Configuration -{ -public: - Configuration() {}; - ~Configuration() {}; - - void removeDataSource(GenericProcessor*); - - int numDataSources() {return dataSources.size();} - DataSource* getSource(int sourceNum) {return dataSources[sourceNum];} - - void addDataSource(DataSource* d) - { - std::cout << "New data source added." << std::endl; - dataSources.add(d); - } - -private: - - OwnedArray<DataSource, CriticalSection> dataSources; -}; - - - - -#endif // __CONFIGURATION_H_9DEA9372__ diff --git a/Source/UI/ControlPanel.cpp b/Source/UI/ControlPanel.cpp index c7cea6acea139220acebc920e162d4d67807c326..c233e8635676f3f711c4fddfb078b66ff9931649 100644 --- a/Source/UI/ControlPanel.cpp +++ b/Source/UI/ControlPanel.cpp @@ -400,6 +400,9 @@ void ControlPanel::buttonClicked(Button* button) if (graph->enableProcessors()) { + if (recordButton->getToggleState()) + graph->getRecordNode()->setParameter(1,10.0f); + audio->beginCallbacks(); masterClock->start(); } diff --git a/Source/UI/ControlPanel.h b/Source/UI/ControlPanel.h index e532a258c99082f704ff3149d807ddc1968bb239..72988db998dcd514274a9c77d8e2d3f3af067b61 100644 --- a/Source/UI/ControlPanel.h +++ b/Source/UI/ControlPanel.h @@ -33,8 +33,6 @@ #include "../OpenGL.h" -//------------------------------------------------------------------------ - /** Displays information and provides buttons to control acquistion and recording. diff --git a/Source/UI/CustomLookAndFeel.cpp b/Source/UI/CustomLookAndFeel.cpp index f6968b9f27af9247e34152ecb8f25d33ff5bb0c3..abc3ec4edf21801634be866a54c999a3db403872 100644 --- a/Source/UI/CustomLookAndFeel.cpp +++ b/Source/UI/CustomLookAndFeel.cpp @@ -27,6 +27,21 @@ CustomLookAndFeel::CustomLookAndFeel() { MemoryInputStream mis(BinaryData::misoserialized, BinaryData::misoserializedSize, false); Miso = new CustomTypeface(mis); + + enum { + PROCESSOR_COLOR = 0x801, + FILTER_COLOR = 0x802, + SINK_COLOR = 0x803, + SOURCE_COLOR = 0x804, + UTILITY_COLOR = 0x805, + }; + + setColour(PROCESSOR_COLOR, Colour(59, 59, 59)); + setColour(FILTER_COLOR, Colour(255, 89, 0)); + setColour(SINK_COLOR, Colour(255, 149, 0)); + setColour(SOURCE_COLOR, Colour(255, 0, 0)); + setColour(UTILITY_COLOR, Colour(90, 80, 80)); + } CustomLookAndFeel::~CustomLookAndFeel() {} @@ -538,4 +553,61 @@ void CustomLookAndFeel::drawGlassPointer (Graphics& g, g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); g.strokePath (p, PathStrokeType (outlineThickness)); +} + +/// ------ combo box ---------------/// + + +void CustomLookAndFeel::drawComboBox (Graphics& g, int width, int height, + const bool isButtonDown, + int buttonX, int buttonY, + int buttonW, int buttonH, + ComboBox& box) +{ + + g.fillAll (box.findColour (ComboBox::backgroundColourId)); + + if (box.isEnabled() && box.hasKeyboardFocus (false)) + { + g.setColour (box.findColour (TextButton::buttonColourId)); + g.drawRect (0, 0, width, height, 2); + } + else + { + g.setColour (box.findColour (ComboBox::outlineColourId)); + g.drawRect (0, 0, width, height); + } + + const float outlineThickness = box.isEnabled() ? (isButtonDown ? 1.2f : 0.5f) : 0.3f; + + const Colour baseColour (Colours::orange);/*LookAndFeelHelpers::createBaseColour (box.findColour (ComboBox::buttonColourId), + box.hasKeyboardFocus (true), + false, isButtonDown) + .withMultipliedAlpha (box.isEnabled() ? 1.0f : 0.5f));*/ + + drawGlassLozenge (g, + buttonX + outlineThickness, buttonY + outlineThickness, + buttonW - outlineThickness * 2.0f, buttonH - outlineThickness * 2.0f, + baseColour, outlineThickness, -1.0f, + true, true, true, true); + + if (box.isEnabled()) + { + const float arrowX = 0.3f; + const float arrowH = 0.2f; + + Path p; + p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), + buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, + buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); + + p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), + buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, + buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); + + g.setColour (box.findColour (ComboBox::arrowColourId)); + g.fillPath (p); + } + + } \ No newline at end of file diff --git a/Source/UI/CustomLookAndFeel.h b/Source/UI/CustomLookAndFeel.h index 2bd37b8b52a2844abea5d669aedaedfad22fcc91..c654933729e1cdf0a5831eaec449f538dc34cbf1 100644 --- a/Source/UI/CustomLookAndFeel.h +++ b/Source/UI/CustomLookAndFeel.h @@ -142,6 +142,13 @@ public: const Typeface::Ptr getTypefaceForFont (const Font& font); + // ======== custom combo box methods: ============================= + + void drawComboBox (Graphics& g, int width, int height, + const bool isButtonDown, + int buttonX, int buttonY, + int buttonW, int buttonH, + ComboBox& box); private: diff --git a/Source/UI/DataViewport.cpp b/Source/UI/DataViewport.cpp index c4c0a1bae57a092dbbafd4f3570a09a75939ebbc..f580e271cf8764cbc2895169757f5aad1caadc21 100644 --- a/Source/UI/DataViewport.cpp +++ b/Source/UI/DataViewport.cpp @@ -63,14 +63,20 @@ DataViewport::~DataViewport() } - void DataViewport::removeTab(int index) { + void DataViewport::destroyTab(int index) { - int newIndex = tabArray->indexOf(index); - tabArray->remove(newIndex); + int newIndex = tabArray->indexOf(index); - getTabbedButtonBar().removeTab(newIndex); + Component* canvas = getTabContentComponent(newIndex); + Component* parent = canvas->getParentComponent(); + parent->removeChildComponent(canvas); - if (tabArray->size() == 0) + tabArray->remove(newIndex); + + removeTab(newIndex); + //getTabbedButtonBar().removeTab(newIndex); + + if (tabArray->size() == 0) setVisible(false); } @@ -79,8 +85,9 @@ DataViewport::~DataViewport() { OpenGLCanvas* canvas = (OpenGLCanvas*) getTabContentComponent(newIndex); - if (canvas != 0) + if (canvas != 0) { canvas->refreshState(); + } } void DataViewport::paint(Graphics& g) diff --git a/Source/UI/DataViewport.h b/Source/UI/DataViewport.h index 3b590ea32439f0b5689cba1de7b788caef387525..03361495ce820fdc0b8cfd0016bc6c25790f5244 100644 --- a/Source/UI/DataViewport.h +++ b/Source/UI/DataViewport.h @@ -49,7 +49,7 @@ public: int addTabToDataViewport(String tabName, Component* componentToAdd); /** Removes a tab with a specified index.*/ - void removeTab(int); + void destroyTab(int); /** Informs the component of the current tab that it's now active.*/ void currentTabChanged(int newIndex, const String& newTabName); diff --git a/Source/UI/EditorViewport.cpp b/Source/UI/EditorViewport.cpp index 8bdb0b2d3e4ab2246d7151806ba080875f6e7db3..0652adc754df3dc3651e1dc7222f0178d22dcbce 100644 --- a/Source/UI/EditorViewport.cpp +++ b/Source/UI/EditorViewport.cpp @@ -28,17 +28,17 @@ EditorViewport::EditorViewport() : message ("Drag-and-drop some rows from the top-left box onto this component!"), - somethingIsBeingDraggedOver (false), shiftDown(false), leftmostEditor(0), + somethingIsBeingDraggedOver(false), shiftDown(false), leftmostEditor(0), insertionPoint(0), componentWantsToMove(false), indexOfMovingComponent(-1), - borderSize(6), tabSize(30), tabButtonSize(15), canEdit(true), currentTab(-1)//, signalChainNeedsSource(true) + borderSize(6), tabSize(30), tabButtonSize(15), canEdit(true), currentTab(-1) { - addMouseListener(this, true); + addMouseListener(this, true); - MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false); - Typeface::Ptr typeface = new CustomTypeface(mis); - font = Font(typeface); - font.setHeight(10); + MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false); + Typeface::Ptr typeface = new CustomTypeface(mis); + font = Font(typeface); + font.setHeight(10); sourceDropImage = ImageCache::getFromMemory (BinaryData::SourceDrop_png, BinaryData::SourceDrop_pngSize); @@ -64,13 +64,11 @@ EditorViewport::EditorViewport() addAndMakeVisible(rightButton); addAndMakeVisible(leftButton); - - } EditorViewport::~EditorViewport() { - deleteAndZero(signalChainManager); + // deleteAndZero(signalChainManager); deleteAllChildren(); } @@ -218,9 +216,10 @@ void EditorViewport::itemDropped (const String& sourceDescription, Component* /* if (activeEditor != 0) { - addChildComponent(activeEditor); activeEditor->setUIComponent(getUIComponent()); - + activeEditor->refreshColors(); + addChildComponent(activeEditor); + lastEditor = activeEditor; signalChainManager->updateVisibleEditors(activeEditor, indexOfMovingComponent, insertionPoint, ADD); @@ -480,8 +479,6 @@ void EditorViewport::mouseDown(const MouseEvent &e) { } } - // selectEditor((GenericEditor*) e.eventComponent); - } void EditorViewport::mouseDrag(const MouseEvent &e) { @@ -572,7 +569,7 @@ void EditorViewport::mouseExit(const MouseEvent &e) { void EditorViewport::checkScrollButtons(int topTab) { - if (editorArray.size() - topTab > 4) + if (signalChainArray.size() - topTab > 4) { downButton->setActive(true); } else { @@ -638,74 +635,115 @@ void EditorViewport::buttonClicked (Button* button) SignalChainTabButton::SignalChainTabButton() : Button("Name"), configurationChanged(true) - { - setRadioGroupId(99); - //setToggleState(false,true); - setClickingTogglesState(true); +{ + setRadioGroupId(99); + setClickingTogglesState(true); - MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false); - Typeface::Ptr typeface = new CustomTypeface(mis); - buttonFont = Font(typeface); - buttonFont.setHeight(14); + MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false); + Typeface::Ptr typeface = new CustomTypeface(mis); + buttonFont = Font(typeface); + buttonFont.setHeight(14); - offset = 0; - } + offset = 0; +} void SignalChainTabButton::clicked() { - //std::cout << "Button clicked: " << firstEditor->getName() << std::endl; - EditorViewport* ev = (EditorViewport*) getParentComponent(); - - scm->updateVisibleEditors(firstEditor, 0, 0, ACTIVATE); - ev->leftmostEditor = offset; - ev->refreshEditors(); + //std::cout << "Button clicked: " << firstEditor->getName() << std::endl; + EditorViewport* ev = (EditorViewport*) getParentComponent(); + + scm->updateVisibleEditors(firstEditor, 0, 0, ACTIVATE); + ev->leftmostEditor = offset; + ev->refreshEditors(); } void SignalChainTabButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown) { - if (getToggleState() == true) - g.setColour(Colours::orange); - else - g.setColour(Colours::darkgrey); - - if (isMouseOver) - g.setColour(Colours::white); - - g.fillEllipse(0,0,getWidth(),getHeight()); - - g.setFont(buttonFont); - g.setColour(Colours::black); - - String n; - - if (num == 0) - n = "A"; - else if (num == 1) - n = "B"; - else if (num == 2) - n = "C"; - else if (num == 3) - n = "D"; - else if (num == 4) - n = "E"; - else if (num == 5) - n = "F"; - else if (num == 6) - n = "G"; - else if (num == 7) - n = "H"; - else if (num == 8) - n = "I"; - else - n = "-"; - - g.drawText(n,0,0,getWidth(),getHeight(),Justification::centred,true); + + ColourGradient grad1, grad2; + + if (getToggleState() == true) { + + grad1 = ColourGradient(Colour(255, 136, 34), 0.0f, 0.0f, + Colour(230, 193, 32), 0.0f, 20.0f, + false); + + grad2 = ColourGradient(Colour(255, 136, 34), 0.0f, 20.0f, + Colour(230, 193, 32), 0.0f, 0.0f, + false); + } + else { + grad2 = ColourGradient(Colour(80, 80, 80), 0.0f, 20.0f, + Colour(120, 120, 120), 0.0f, 0.0f, + false); + + grad1 = ColourGradient(Colour(80, 80, 80), 0.0f, 0.0f, + Colour(120, 120, 120), 0.0f, 20.0f, + false); + } + + if (isMouseOver) { + + grad1.multiplyOpacity(0.7f); + grad2.multiplyOpacity(0.7f); + // grad1 = ColourGradient(Colour(255, 255, 255), 0.0f, 20.0f, + // Colour(180, 180, 180), 0.0f, 0.0f, + // false); + + // grad2 = ColourGradient(Colour(255, 255, 255), 0.0f, 0.0f, + // Colour(180, 180, 180), 0.0f, 20.0f, + // false); + } + + if (isButtonDown) { + + // ColourGradient grad3 = grad1; + // grad1 = grad2; + // grad2 = grad3; + // grad1.multiplyOpacity(0.7f); + // grad2.multiplyOpacity(0.7f); + } + g.setGradientFill(grad2); + g.fillEllipse(0,0,getWidth(),getHeight()); + + g.setGradientFill(grad1); + g.fillEllipse(2,2,getWidth()-4,getHeight()-4); + + g.setFont(buttonFont); + g.setColour(Colours::black); + + String n; + + if (num == 0) + n = "A"; + else if (num == 1) + n = "B"; + else if (num == 2) + n = "C"; + else if (num == 3) + n = "D"; + else if (num == 4) + n = "E"; + else if (num == 5) + n = "F"; + else if (num == 6) + n = "G"; + else if (num == 7) + n = "H"; + else if (num == 8) + n = "I"; + else + n = "-"; + + g.drawText(n,0,0,getWidth(),getHeight(),Justification::centred,true); +} + // how about some loading and saving? @@ -811,10 +849,7 @@ const String EditorViewport::saveState(const File& file) { splitPoints.add(nextProcessor); - if (nextProcessor->isSplitter()) - nextProcessor->switchDest(0); - else - nextProcessor->switchSource(0); + nextProcessor->switchIO(0); } } else { @@ -826,22 +861,19 @@ const String EditorViewport::saveState(const File& file) nextProcessor = splitPoints.getFirst(); splitPoints.remove(0); + nextProcessor->switchIO(1); + signalChain->addChildElement(switchNodeXml(nextProcessor)); + if (nextProcessor->isMerger()) { - std::cout << " Switching merger source." << std::endl; - nextProcessor->switchSource(1); - signalChain->addChildElement(switchNodeXml(nextProcessor)); insertionPt = 0; moveForward = false; - } else { - std::cout << " Switching splitter dest." << std::endl; - nextProcessor->switchDest(1); - signalChain->addChildElement(switchNodeXml(nextProcessor)); + } else { insertionPt = 1; moveForward = true; } - editor = (GenericEditor*) nextProcessor->getEditor(); + editor = nextProcessor->getEditor(); } else { @@ -882,7 +914,6 @@ const String EditorViewport::loadState(const File& file) { std::cout << "File not found." << std::endl; delete xml; - // don't do anything return "Not a valid file."; } @@ -948,8 +979,5 @@ const String EditorViewport::loadState(const File& file) delete xml; return "Everything went ok."; - - // refreshEditors(); - } diff --git a/Source/UI/EditorViewport.h b/Source/UI/EditorViewport.h index 0d547454ad591b2e9eb5b942be7ea689b91c1d79..ce01d43a358378870ac2acea1d6c8125cf65e582 100644 --- a/Source/UI/EditorViewport.h +++ b/Source/UI/EditorViewport.h @@ -64,14 +64,11 @@ public: // Creating and deleting editors: void deleteNode(GenericEditor* editor); - // void updateVisibleEditors(GenericEditor* activeEditor, int action); void selectEditor(GenericEditor* e); void makeEditorVisible(GenericEditor* e); void refreshEditors(); - // void setActiveEditor(GenericEditor* e) {activeEditor = e; updateVisibleEditors();} - void signalChainCanBeEdited(bool t); // DragAndDropTarget methods: @@ -104,7 +101,7 @@ public: void checkScrollButtons(int topTab); - int leftmostEditor; + int leftmostEditor; private: @@ -115,23 +112,16 @@ private: bool canEdit; GenericEditor* lastEditor; - //ProcessorGraph* graph; - //DataViewport* tabComponent; - Array<GenericEditor*, CriticalSection> editorArray; Array<SignalChainTabButton*, CriticalSection> signalChainArray; - SignalChainManager* signalChainManager; + ScopedPointer<SignalChainManager> signalChainManager; Font font; Image sourceDropImage; - // int activeTab; - - void createNewTab(GenericEditor* editor); void removeTab(int tabIndex); - //void drawTabs(); int borderSize, tabSize, tabButtonSize; @@ -152,8 +142,6 @@ private: void resized(); - //bool signalChainNeedsSource; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EditorViewport); }; @@ -161,7 +149,7 @@ private: class SignalChainTabButton : public Button { public: - SignalChainTabButton();// : Button("Name") {configurationChanged = true;} + SignalChainTabButton(); ~SignalChainTabButton() {} void setEditor(GenericEditor* p) {firstEditor = p;} @@ -175,8 +163,6 @@ public: int offset; - - private: GenericEditor* firstEditor; @@ -187,7 +173,6 @@ private: void clicked(); - enum actions {ADD, MOVE, REMOVE, ACTIVATE}; int num; @@ -195,7 +180,6 @@ private: Font buttonFont; - }; #endif // __EDITORVIEWPORT_H_80260F3F__ diff --git a/Source/UI/InfoLabel.cpp b/Source/UI/InfoLabel.cpp index 9aa437b50d5b946b8485361ef465008a5ffe91f9..2da53f2776bcb38a4e13b50c8a6f42ddedee2a0b 100644 --- a/Source/UI/InfoLabel.cpp +++ b/Source/UI/InfoLabel.cpp @@ -105,13 +105,11 @@ void InfoLabel::drawLabel() } -void InfoLabel::resized() +void InfoLabel::canvasWasResized() { layout.SetLineLength(getWidth()-45); - canvasWasResized(); - } int InfoLabel::getTotalHeight() diff --git a/Source/UI/InfoLabel.h b/Source/UI/InfoLabel.h index f3fd77740cfb20b11627566d38883f1f8ba3027e..4967de8fc93dfd61b871a02afeeeaecda79adb6b 100644 --- a/Source/UI/InfoLabel.h +++ b/Source/UI/InfoLabel.h @@ -54,7 +54,7 @@ private: int getTotalHeight(); - void resized(); + void canvasWasResized(); FTSimpleLayout layout; String infoString; diff --git a/Source/UI/ProcessorList.cpp b/Source/UI/ProcessorList.cpp index 6c2af6c893fdb80ce881f95fc0a546f8a995b9b7..405b0eed98c0ebd65f23e7a7b850d08214f5479f 100644 --- a/Source/UI/ProcessorList.cpp +++ b/Source/UI/ProcessorList.cpp @@ -36,21 +36,35 @@ ProcessorList::ProcessorList() : isDragging(false), yBuffer(1) { + enum { + PROCESSOR_COLOR = 801, + FILTER_COLOR = 802, + SINK_COLOR = 803, + SOURCE_COLOR = 804, + UTILITY_COLOR = 805, + }; + + setColour(PROCESSOR_COLOR, Colour(59, 59, 59)); + setColour(FILTER_COLOR, Colour(27, 86, 224));//Colour(255, 89, 0)); + setColour(SINK_COLOR, Colour(41, 76, 158));//Colour(255, 149, 0)); + setColour(SOURCE_COLOR, Colour(48, 67, 112)); //Colour(255, 0, 0)); + setColour(UTILITY_COLOR, Colour(90, 80, 80)); + ProcessorListItem* sources = new ProcessorListItem("Sources"); sources->addSubItem(new ProcessorListItem("Intan Demo Board")); sources->addSubItem(new ProcessorListItem("Signal Generator")); //sources->addSubItem(new ProcessorListItem("Custom FPGA")); - //sources->addSubItem(new ProcessorListItem("File Reader")); + sources->addSubItem(new ProcessorListItem("File Reader")); sources->addSubItem(new ProcessorListItem("Event Generator")); ProcessorListItem* filters = new ProcessorListItem("Filters"); filters->addSubItem(new ProcessorListItem("Bandpass Filter")); //filters->addSubItem(new ProcessorListItem("Resampler")); - //filters->addSubItem(new ProcessorListItem("Spike Detector")); + filters->addSubItem(new ProcessorListItem("Spike Detector")); ProcessorListItem* sinks = new ProcessorListItem("Sinks"); sinks->addSubItem(new ProcessorListItem("LFP Viewer")); - //sinks->addSubItem(new ProcessorListItem("Spike Display")); + sinks->addSubItem(new ProcessorListItem("Spike Viewer")); sinks->addSubItem(new ProcessorListItem("WiFi Output")); ProcessorListItem* utilities = new ProcessorListItem("Utilities"); @@ -153,10 +167,12 @@ void ProcessorList::drawItems() void ProcessorList::drawItem(ProcessorListItem* item) { - - glColor4f(item->color.getFloatRed(), - item->color.getFloatGreen(), - item->color.getFloatBlue(), + + Colour c = findColour(item->colorId); + + glColor4f(c.getFloatRed(), + c.getFloatGreen(), + c.getFloatBlue(), 1.0f); glBegin(GL_POLYGON); @@ -322,9 +338,7 @@ int ProcessorList::getTotalHeight() return totalHeight; } -void ProcessorList::resized() {canvasWasResized();} - -void ProcessorList::mouseDown(const MouseEvent& e) +void ProcessorList::mouseDownInCanvas(const MouseEvent& e) { isDragging = false; @@ -370,12 +384,10 @@ void ProcessorList::mouseDown(const MouseEvent& e) } } - mouseDownInCanvas(e); - repaint(); } -void ProcessorList::mouseDrag(const MouseEvent& e) +void ProcessorList::mouseDragInCanvas(const MouseEvent& e) { if (e.getMouseDownX() < getWidth()-getScrollBarWidth() && !(isDragging)) @@ -410,7 +422,7 @@ void ProcessorList::mouseDrag(const MouseEvent& e) Image dragImage (Image::ARGB, 100, 15, true); Graphics g(dragImage); - g.setColour (fli->color); + g.setColour (findColour(fli->colorId)); g.fillAll(); g.setColour(Colours::white); g.setFont(14); @@ -427,14 +439,8 @@ void ProcessorList::mouseDrag(const MouseEvent& e) } } - mouseDragInCanvas(e); } -void ProcessorList::mouseMove(const MouseEvent& e) {mouseMoveInCanvas(e);} -void ProcessorList::mouseUp(const MouseEvent& e) {mouseUpInCanvas(e);} -void ProcessorList::mouseWheelMove(const MouseEvent& e, float a, float b) {mouseWheelMoveInCanvas(e,a,b);} - - ProcessorListItem::ProcessorListItem(const String& name_) : name(name_), open(true), selected(false) { } @@ -502,22 +508,35 @@ void ProcessorListItem::setParentName(const String& name) { parentName = name; + enum { + PROCESSOR_COLOR = 801, + FILTER_COLOR = 802, + SINK_COLOR = 803, + SOURCE_COLOR = 804, + UTILITY_COLOR = 805, + }; + if (parentName.equalsIgnoreCase("Processors")) { - color = Colour(59, 59, 59); + colorId = PROCESSOR_COLOR; + //color = Colour(59, 59, 59); } else if (parentName.equalsIgnoreCase("Filters")) { - color = Colour(255, 89, 0); + colorId = FILTER_COLOR; + //color = Colour(255, 89, 0); } else if (parentName.equalsIgnoreCase("Sinks")) { - color = Colour(255, 149, 0); + colorId = SINK_COLOR; + //color = Colour(255, 149, 0); } else if (parentName.equalsIgnoreCase("Sources")) { - color = Colour(255, 0, 0); + colorId = SOURCE_COLOR; + //color = Colour(255, 0, 0); } else { - color = Colour(90, 80, 80); + colorId = UTILITY_COLOR; + //color = Colour(90, 80, 80); } } diff --git a/Source/UI/ProcessorList.h b/Source/UI/ProcessorList.h index 57150369ab85c239f40e2c9aff797bbb61db8f13..faf6b6558d3abfae1e6082185908b2b1f2c53550 100644 --- a/Source/UI/ProcessorList.h +++ b/Source/UI/ProcessorList.h @@ -78,16 +78,10 @@ private: int totalHeight, itemHeight, subItemHeight; int xBuffer, yBuffer; - //UIComponent* UI; - String category; - void resized(); - void mouseDown(const MouseEvent& e); - void mouseDrag(const MouseEvent& e); - void mouseMove(const MouseEvent& e); - void mouseUp(const MouseEvent& e); - void mouseWheelMove(const MouseEvent&, float, float); + void mouseDownInCanvas(const MouseEvent& e); + void mouseDragInCanvas(const MouseEvent& e); ProcessorListItem* baseItem; @@ -95,7 +89,7 @@ private: }; -class ProcessorListItem +class ProcessorListItem //: public Component { public: ProcessorListItem(const String& name); @@ -120,7 +114,8 @@ public: const String& getParentName(); void setParentName(const String& name); - Colour color; + //Colour color; + int colorId; private: diff --git a/Source/UI/SignalChainManager.cpp b/Source/UI/SignalChainManager.cpp index 29f77b0406c8837d15c45acbdb823209bb76b291..3312bd856da6622aa1b96357a30c7f7162029831 100644 --- a/Source/UI/SignalChainManager.cpp +++ b/Source/UI/SignalChainManager.cpp @@ -175,7 +175,7 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, // need to inform the other source that its merger has disappeared if (p->isMerger()) { - p->switchSource(); + p->switchIO(); if (p->getSourceNode() != 0) p->getSourceNode()->setDestNode(0); } @@ -244,12 +244,7 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, GenericProcessor* source = 0; GenericProcessor* dest = (GenericProcessor*) editorArray[0]->getProcessor(); - if (!dest->isMerger()) - dest->setSourceNode(source); // set first source as 0 - else - dest->setMergerSourceNode(source); - - // std::cout << " " << dest->getName() << "::"; + dest->setSourceNode(source); for (int n = 1; n < editorArray.size(); n++) { @@ -257,23 +252,12 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, dest = (GenericProcessor*) editorArray[n]->getProcessor(); source = (GenericProcessor*) editorArray[n-1]->getProcessor(); - //if (!dest->isMerger()) - dest->setSourceNode(source); - //else - // dest->setMergerSourceNode(source); - - //std::cout << dest->getName() << "::"; + dest->setSourceNode(source); } - if (!dest->isSplitter()) - dest->setDestNode(0); // set first source as 0 - else - dest->setSplitterDestNode(0); - // dest->setDestNode(0); // set last dest as 0 - - // std::cout << std::endl; - }// + dest->setDestNode(0); + } // Step 3: check for new tabs if (action != ACTIVATE) { @@ -284,8 +268,6 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, { GenericProcessor* p = (GenericProcessor*) editorArray[n]->getProcessor(); - // std::cout << editorArray[n]->tabNumber() << std::endl; - if (p->getSourceNode() == 0)// && editorArray[n]->tabNumber() == -1) { @@ -316,26 +298,12 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, } } - - - // Step 4: Refresh editors in editor array, based on active editor for (int n = 0; n < editorArray.size(); n++) { editorArray[n]->setVisible(false); } - // int activeChain; - - // for (int n = 0; n < signalChainArray.size(); n++) - // { - // if (signalChainArray[n]->getToggleState()) - // { - // activeChain = n; - // break; - // } - // } - editorArray.clear(); std::cout << "Cleared editor array." << std::endl; @@ -361,18 +329,6 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, editorToAdd = 0; } - - // if (currentProcessor->isMerger()) - // { - // std::cout << "It's a merger!" << std::endl; - - //if (currentProcessor->getSource() == activeChain) - // editorToAdd->switchSource(0); - // else - // editorToAdd->switchSource(1); - - // } - } editorToAdd = activeEditor; @@ -397,8 +353,6 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, if (dest->getSourceNode() != currentProcessor) editorToAdd->switchSource(); - // else - // editorToAdd->switchSource(1); } @@ -410,8 +364,6 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, } - //std::cout << "OK1." << std::endl; - // Step 5: check the validity of the signal chain if (true) { bool enable = true; @@ -426,8 +378,6 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, } else { - //bool sourceIsInChain = true; - for (int n = 0; n < editorArray.size()-1; n++) { GenericProcessor* source = (GenericProcessor*) editorArray[n]->getProcessor(); @@ -464,37 +414,42 @@ void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, } // Step 7: update all settings - if (action != ACTIVATE) { + if (true) {//action != ACTIVATE) { std::cout << "Updating settings." << std::endl; + Array<GenericProcessor*> splitters; + for (int n = 0; n < signalChainArray.size(); n++) - { + { // iterate through signal chains - GenericEditor* source = (GenericEditor*) signalChainArray[n]->getEditor(); - GenericProcessor* p = (GenericProcessor*) source->getProcessor(); + GenericEditor* source = signalChainArray[n]->getEditor(); + GenericProcessor* p = source->getProcessor(); - p->updateSettings(); + p->update(); + + if (p->isSplitter()) + { + splitters.add(p); + } GenericProcessor* dest = p->getDestNode(); while (dest != 0) - { - dest->updateSettings(); + { // iterate through processors + dest->update(); dest = dest->getDestNode(); + + if (dest == 0 && splitters.size() > 0) + { + splitters.getFirst()->switchIO(); + dest = splitters[0]->getDestNode(); + splitters.remove(0); + } } } } - // std::cout << "OK2." << std::endl; - - // Step 8: make sure all editors are visible, and refresh - // for (int n = 0; n < editorArray.size(); n++) - // { - // std::cout << "Editor " << n << ": " << editorArray[n]->getName() << std::endl; - // editorArray[n]->setVisible(true); - // } - std::cout << "Finished adding new editor." << std::endl << std::endl << std::endl; diff --git a/Source/UI/UIComponent.cpp b/Source/UI/UIComponent.cpp index 44d282ca6bb6d27de4204ea31b5fcabff57ce273..48d126c1e4cd4bee80cbe2693df2560f1d768f93 100644 --- a/Source/UI/UIComponent.cpp +++ b/Source/UI/UIComponent.cpp @@ -39,9 +39,8 @@ UIComponent::UIComponent (MainWindow* mainWindow_, ProcessorGraph* pgraph, Audio std::cout << "Created data viewport." << std::endl; - editorViewport = new EditorViewport();//(processorGraph, dataViewport); - //processorGraph->setEditorViewport(editorViewport); - + editorViewport = new EditorViewport(); + addAndMakeVisible(editorViewport); std::cout << "Created filter viewport." << std::endl; @@ -55,23 +54,16 @@ UIComponent::UIComponent (MainWindow* mainWindow_, ProcessorGraph* pgraph, Audio std::cout << "Created control panel." << std::endl; processorList = new ProcessorList(); - //filterList->setUIComponent(this); addAndMakeVisible(processorList); std::cout << "Created filter list." << std::endl; messageCenter = new MessageCenter(); - //processorGraph->addActionListener(messageCenter); addActionListener(messageCenter); addAndMakeVisible(messageCenter); std::cout << "Created message center." << std::endl; - config = new Configuration(); - //processorGraph->setConfiguration(config); - - std::cout << "Created configuration object." << std::endl; - setBounds(0,0,500,400); std::cout << "Component width = " << getWidth() << std::endl; @@ -79,10 +71,8 @@ UIComponent::UIComponent (MainWindow* mainWindow_, ProcessorGraph* pgraph, Audio std::cout << "UI component data viewport: " << dataViewport << std::endl; - std::cout << "Finished UI stuff." << std::endl << std::endl << std::endl; - processorGraph->setUIComponent(this); processorList->setUIComponent(this); editorViewport->setUIComponent(this); @@ -96,7 +86,6 @@ UIComponent::~UIComponent() { deleteAllChildren(); - deleteAndZero(config); deleteAndZero(infoLabel); processorGraph = 0; @@ -150,6 +139,17 @@ void UIComponent::resized() if (messageCenter != 0) messageCenter->setBounds(6,h-35,w-241,30); + // for debugging purposes: + if (false) { + dataViewport->setVisible(false); + editorViewport->setVisible(false); + processorList->setVisible(false); + messageCenter->setVisible(false); + controlPanel->setVisible(false); + editorViewportButton->setVisible(false); + } + + } void UIComponent::disableCallbacks() @@ -262,8 +262,6 @@ void EditorViewportButton::drawName() font->FaceSize(23); font->Render("SIGNAL CHAIN"); - - } void EditorViewportButton::drawButton() diff --git a/Source/UI/UIComponent.h b/Source/UI/UIComponent.h index 2c374b53f66e4d4573a4d0c92f7a50e51239a34e..68e0cc9e5df35448ddb826f9f11b5f8b0f8b1055 100644 --- a/Source/UI/UIComponent.h +++ b/Source/UI/UIComponent.h @@ -31,7 +31,6 @@ #include "EditorViewport.h" #include "DataViewport.h" #include "MessageCenter.h" -#include "Configuration.h" #include "../Processors/ProcessorGraph.h" #include "../Audio/AudioComponent.h" #include "../MainWindow.h" @@ -71,7 +70,6 @@ public: EditorViewport* getEditorViewport() {return editorViewport;} ProcessorList* getProcessorList() {return processorList;} DataViewport* getDataViewport() {return dataViewport;} - Configuration* getConfiguration() {return config;} ProcessorGraph* getProcessorGraph() {return processorGraph;} ControlPanel* getControlPanel() {return controlPanel;} MessageCenter* getMessageCenter() {return messageCenter;} @@ -95,7 +93,6 @@ private: ProcessorList* processorList; ControlPanel* controlPanel; MessageCenter* messageCenter; - Configuration* config; InfoLabel* infoLabel; MainWindow* mainWindow; diff --git a/open-ephys.jucer b/open-ephys.jucer index 2768d9df5014df67ecc942d65400bef9ec6de543..5eb088f9745b0109761d33258566279cdbe6740d 100644 --- a/open-ephys.jucer +++ b/open-ephys.jucer @@ -10,15 +10,16 @@ pluginRTASCategory="" bundleIdentifier="" jucerVersion="3.0.0"> <EXPORTFORMATS> <XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK" - juceFolder="JuceLibraryCode" extraLinkerFlags="-lftdi -lftgl"/> + juceFolder="JuceLibraryCode" extraLinkerFlags="-lftdi -lftgl" + objCExtraSuffix="fea2mT"/> <LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="JuceLibraryCode" - extraLinkerFlags="-lftdi -lftgl" extraCompilerFlags="-export-dynamic"/> + extraLinkerFlags="-lftdi -lftgl" extraCompilerFlags="-export-dynamic -pg"/> </EXPORTFORMATS> <CONFIGURATIONS> <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="open-ephys" - osxSDK="default" osxCompatibility="default"/> + osxSDK="default" osxCompatibility="default" osxArchitecture="default"/> <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="open-ephys" - osxSDK="default" osxCompatibility="default"/> + osxSDK="default" osxCompatibility="default" osxArchitecture="default"/> </CONFIGURATIONS> <MAINGROUP id="h3HbSTV" name="open-ephys"> <GROUP id="0wpTCpt" name="Resources"> @@ -47,6 +48,52 @@ </GROUP> <GROUP id="W2L6BdA" name="Images"> <GROUP id="Gu1BsKu" name="Icons"> + <FILE id="AQfzTI0" name="RadioButtons-01.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons-01.png"/> + <FILE id="zaiYTpn" name="RadioButtons-02.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons-02.png"/> + <FILE id="tMMIgNQ" name="RadioButtons-03.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons-03.png"/> + <FILE id="izT7ken" name="RadioButtons-04.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons-04.png"/> + <FILE id="wUnR602" name="RadioButtons-05.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons-05.png"/> + <FILE id="imnUJ17" name="RadioButtons_neutral-01.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons_neutral-01.png"/> + <FILE id="lSUFFn" name="RadioButtons_neutral-02.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons_neutral-02.png"/> + <FILE id="RLptoX" name="RadioButtons_neutral-03.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons_neutral-03.png"/> + <FILE id="cTSMIj9" name="RadioButtons_neutral-04.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons_neutral-04.png"/> + <FILE id="e2xa4yY" name="RadioButtons_neutral-05.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons_neutral-05.png"/> + <FILE id="uRp98Z6" name="RadioButtons_selected-01.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected-01.png"/> + <FILE id="TSUeLsT" name="RadioButtons_selected-02.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected-02.png"/> + <FILE id="3iZ1q0" name="RadioButtons_selected-03.png" compile="0" resource="1" + file="Resources/Images/Icons/RadioButtons_selected-03.png"/> + <FILE id="eBBTz15" name="RadioButtons_selected-04.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected-04.png"/> + <FILE id="3UcfCgS" name="RadioButtons_selected-05.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected-05.png"/> + <FILE id="dwuGoW2" name="RadioButtons_selected_over-01.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected_over-01.png"/> + <FILE id="sNKpDX4" name="RadioButtons_selected_over-02.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected_over-02.png"/> + <FILE id="3hxkdcI" name="RadioButtons_selected_over-03.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected_over-03.png"/> + <FILE id="NJA55tz" name="RadioButtons_selected_over-04.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected_over-04.png"/> + <FILE id="SDmWsOz" name="RadioButtons_selected_over-05.png" compile="0" + resource="1" file="Resources/Images/Icons/RadioButtons_selected_over-05.png"/> + <FILE id="rdA7uYL" name="noise_wave.png" compile="0" resource="1" file="Resources/Images/Icons/noise_wave.png"/> + <FILE id="s0uKcoP" name="saw_wave.png" compile="0" resource="1" file="Resources/Images/Icons/saw_wave.png"/> + <FILE id="4jA1Wxu" name="sine_wave.png" compile="0" resource="1" file="Resources/Images/Icons/sine_wave.png"/> + <FILE id="goY3ZC" name="square_wave.png" compile="0" resource="1" file="Resources/Images/Icons/square_wave.png"/> + <FILE id="gkPmriI" name="triangle_wave.png" compile="0" resource="1" + file="Resources/Images/Icons/triangle_wave.png"/> <FILE id="wI03PLF" name="wifi.png" compile="0" resource="1" file="Resources/Images/Icons/wifi.png"/> <FILE id="p1qlCZ5" name="SourceDrop.png" compile="0" resource="1" file="Resources/Images/Icons/SourceDrop.png"/> <FILE id="nWbYpu" name="DefaultDataSource.png" compile="0" resource="1" @@ -137,6 +184,12 @@ file="Source/Audio/AudioComponent.h"/> </GROUP> <GROUP id="yQmqZWk" name="Processors"> + <FILE id="pQaYQiE" name="Parameter.cpp" compile="1" resource="0" file="Source/Processors/Parameter.cpp"/> + <FILE id="0jxvc4H" name="Parameter.h" compile="0" resource="0" file="Source/Processors/Parameter.h"/> + <FILE id="arRy5R" name="SpikeDisplayNode.cpp" compile="1" resource="0" + file="Source/Processors/SpikeDisplayNode.cpp"/> + <FILE id="VwDxj" name="SpikeDisplayNode.h" compile="0" resource="0" + file="Source/Processors/SpikeDisplayNode.h"/> <FILE id="Poqus0b" name="WiFiOutput.cpp" compile="1" resource="0" file="Source/Processors/WiFiOutput.cpp"/> <FILE id="IklsJpw" name="WiFiOutput.h" compile="0" resource="0" file="Source/Processors/WiFiOutput.h"/> <FILE id="ZuMpSio" name="LfpDisplayNode.cpp" compile="1" resource="0" @@ -150,6 +203,39 @@ <FILE id="DXYynnz" name="Splitter.h" compile="0" resource="0" file="Source/Processors/Utilities/Splitter.h"/> </GROUP> <GROUP id="W4eqkOy" name="Visualization"> + <GROUP id="g8GOfh" name="SpikePlotting"> + <FILE id="PzmX0I" name="StereotrodePlot.cpp" compile="1" resource="0" + file="Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp"/> + <FILE id="LPK6G1" name="StereotrodePlot.h" compile="0" resource="0" + file="Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h"/> + <FILE id="EgoljI" name="ElectrodePlot.cpp" compile="1" resource="0" + file="Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp"/> + <FILE id="oFUMq0" name="ElectrodePlot.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h"/> + <FILE id="Qq75l" name="BaseUIElement.cpp" compile="1" resource="0" + file="Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp"/> + <FILE id="PZdkKU" name="BaseUIElement.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/BaseUIElement.h"/> + <FILE id="lFRVqc" name="GenericAxes.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp"/> + <FILE id="BP8BOa" name="GenericAxes.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/GenericAxes.h"/> + <FILE id="f7vOFh" name="PlotUtils.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp"/> + <FILE id="TQfHuh" name="PlotUtils.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/PlotUtils.h"/> + <FILE id="d3ducO" name="ProjectionAxes.cpp" compile="1" resource="0" + file="Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp"/> + <FILE id="BdHvyv" name="ProjectionAxes.h" compile="0" resource="0" + file="Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h"/> + <FILE id="RnnkTt" name="SimpleKeyEvent.h" compile="0" resource="0" + file="Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h"/> + <FILE id="dP2Ikw" name="TetrodePlot.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp"/> + <FILE id="SH9Un2" name="TetrodePlot.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/TetrodePlot.h"/> + <FILE id="yg1Xuq" name="WaveAxes.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp"/> + <FILE id="cZX4SM" name="WaveAxes.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/WaveAxes.h"/> + </GROUP> + <FILE id="ajAJi" name="SpikeObject.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikeObject.cpp"/> + <FILE id="xqF5zL" name="SpikeObject.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikeObject.h"/> + <FILE id="jGEqDp" name="SpikeDisplayCanvas.cpp" compile="1" resource="0" + file="Source/Processors/Visualization/SpikeDisplayCanvas.cpp"/> + <FILE id="LVHMu2" name="SpikeDisplayCanvas.h" compile="0" resource="0" + file="Source/Processors/Visualization/SpikeDisplayCanvas.h"/> + <FILE id="yDPZGpt" name="Visualizer.h" compile="0" resource="0" file="Source/Processors/Visualization/Visualizer.h"/> <FILE id="BX1Vj3V" name="DataWindow.cpp" compile="1" resource="0" file="Source/Processors/Visualization/DataWindow.cpp"/> <FILE id="l2VKLuP" name="DataWindow.h" compile="0" resource="0" file="Source/Processors/Visualization/DataWindow.h"/> <FILE id="2rXPco7" name="LfpDisplayCanvas.cpp" compile="1" resource="0" @@ -164,13 +250,19 @@ file="Source/Processors/SpikeDetector.cpp"/> <FILE id="jIX00WN" name="SpikeDetector.h" compile="0" resource="0" file="Source/Processors/SpikeDetector.h"/> - <FILE id="sKJ2lid" name="FileReader.cpp" compile="1" resource="0" file="Source/Processors/FileReader.cpp"/> - <FILE id="9o71Tr2" name="FileReader.h" compile="0" resource="0" file="Source/Processors/FileReader.h"/> <FILE id="gZRZq2O" name="AudioNode.cpp" compile="1" resource="0" file="Source/Processors/AudioNode.cpp"/> <FILE id="ZPSmLKn" name="AudioNode.h" compile="0" resource="0" file="Source/Processors/AudioNode.h"/> <FILE id="hGnGAjh" name="EventNode.cpp" compile="1" resource="0" file="Source/Processors/EventNode.cpp"/> <FILE id="dUtRN6" name="EventNode.h" compile="0" resource="0" file="Source/Processors/EventNode.h"/> <GROUP id="AqvwO6w" name="Editors"> + <FILE id="s5YUmi" name="SpikeDisplayEditor.cpp" compile="1" resource="0" + file="Source/Processors/Editors/SpikeDisplayEditor.cpp"/> + <FILE id="EE43GV" name="SpikeDisplayEditor.h" compile="0" resource="0" + file="Source/Processors/Editors/SpikeDisplayEditor.h"/> + <FILE id="2XqqPOS" name="VisualizerEditor.cpp" compile="1" resource="0" + file="Source/Processors/Editors/VisualizerEditor.cpp"/> + <FILE id="CUHGPJF" name="VisualizerEditor.h" compile="0" resource="0" + file="Source/Processors/Editors/VisualizerEditor.h"/> <FILE id="bsIZbuu" name="MergerEditor.cpp" compile="1" resource="0" file="Source/Processors/Editors/MergerEditor.cpp"/> <FILE id="vfmEY5L" name="MergerEditor.h" compile="0" resource="0" file="Source/Processors/Editors/MergerEditor.h"/> @@ -287,10 +379,6 @@ <FILE id="bWElQSS" name="DataViewport.cpp" compile="1" resource="0" file="Source/UI/DataViewport.cpp"/> <FILE id="mMoQ3ls" name="DataViewport.h" compile="0" resource="0" file="Source/UI/DataViewport.h"/> - <FILE id="iFsLzAy" name="Configuration.cpp" compile="1" resource="0" - file="Source/UI/Configuration.cpp"/> - <FILE id="vNTFgW9" name="Configuration.h" compile="0" resource="0" - file="Source/UI/Configuration.h"/> <FILE id="rRa3X6v" name="MessageCenter.cpp" compile="1" resource="0" file="Source/UI/MessageCenter.cpp"/> <FILE id="Gwnvgdy" name="MessageCenter.h" compile="0" resource="0"