/* SpiralSound * Copyleft (C) 2001 David Griffiths * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StreamPlugin.h" #include "StreamPluginGUI.h" #include #include "SpiralIcon.xpm" #include "../../NoteTable.h" #include #include "../../RiffWav.h" using namespace std; static const float TRIG_THRESH = 0.1; static const float BUFSECONDS = 1.0f; extern "C" { SpiralPlugin* SpiralPlugin_CreateInstance() { return new StreamPlugin; } char** SpiralPlugin_GetIcon() { return SpiralIcon_xpm; } int SpiralPlugin_GetID() { return 0x0119; } string SpiralPlugin_GetGroupName() { return "Delay/Sampling"; } } /////////////////////////////////////////////////////// StreamPlugin::StreamPlugin() : m_SampleRate (44100), m_SampleSize (256), m_StreamPos (0), m_GlobalPos (0), m_Pitch (1.0f), m_SamplePos (-1), m_Pos (0), m_Mode(STOPM) { m_PluginInfo.Name = "Stream"; m_PluginInfo.Width = 245; m_PluginInfo.Height = 165; m_PluginInfo.NumInputs = 3; m_PluginInfo.NumOutputs = 3; m_PluginInfo.PortTips.push_back ("Pitch CV"); m_PluginInfo.PortTips.push_back ("Play Trigger"); m_PluginInfo.PortTips.push_back ("Stop Trigger"); m_PluginInfo.PortTips.push_back ("Left Out"); m_PluginInfo.PortTips.push_back ("Right Out"); m_PluginInfo.PortTips.push_back ("Finish Trigger"); m_GUIArgs.Volume = 1.0f; m_GUIArgs.PitchMod = 1.0f; m_GUIArgs.PlayOut = false; m_AudioCH->Register ("Volume", &m_GUIArgs.Volume); m_AudioCH->Register ("Pitch", &m_GUIArgs.PitchMod, ChannelHandler::INPUT); m_AudioCH->RegisterData ("FileName", ChannelHandler::INPUT, &m_GUIArgs.FileName, sizeof (m_GUIArgs.FileName)); m_AudioCH->Register ("Time", &m_GUIArgs.Time); m_AudioCH->Register ("TimeOut", &m_GUIArgs.TimeOut, ChannelHandler::OUTPUT); m_AudioCH->Register ("MaxTime", &m_GUIArgs.MaxTime, ChannelHandler::OUTPUT); m_AudioCH->Register ("Playing", &m_GUIArgs.PlayOut, ChannelHandler::OUTPUT); } StreamPlugin::~StreamPlugin() { } PluginInfo &StreamPlugin::Initialise(const HostInfo *Host) { PluginInfo& Info = SpiralPlugin::Initialise(Host); return Info; } SpiralGUIType *StreamPlugin::CreateGUI() { return new StreamPluginGUI(m_PluginInfo.Width, m_PluginInfo.Height, this, m_AudioCH, m_HostInfo); } void StreamPlugin::Execute() { if (m_File.IsOpen()) { for (int n=0; nBUFSIZE; n++) { bool FinTrig = false; float CVPitch = GetInput(0, n)*10.0f; if (GetInput (1, n) > 0) m_Mode = PLAYM; if (GetInput (2, n) > 0) { m_Mode = STOPM; m_Pos = 0; m_GlobalPos = 0; m_StreamPos = 0; } if (m_Pos<0) { m_Pos = m_SampleSize - 1; m_StreamPos -= m_SampleSize; FinTrig = m_StreamPos < 0; if (FinTrig) { m_StreamPos = m_File.GetSize() - m_SampleSize; m_GlobalPos = m_StreamPos; } m_File.SeekToChunk (m_StreamPos); if ((m_File.GetSize() - m_StreamPos) < 256) m_SampleSize = m_File.GetSize() - m_StreamPos; else m_SampleSize = 256; m_File.LoadChunk (m_SampleSize, m_SampleL, m_SampleR); } else if (m_Pos >= m_SampleSize) { m_Pos = 0; m_StreamPos += m_SampleSize; FinTrig = m_StreamPos >= m_File.GetSize(); if (FinTrig) { m_StreamPos = 0; m_GlobalPos = 0; } m_File.SeekToChunk (m_StreamPos); if ((m_File.GetSize() - m_StreamPos) < 256) m_SampleSize = m_File.GetSize() - m_StreamPos; else m_SampleSize = 256; m_File.LoadChunk (m_SampleSize, m_SampleL, m_SampleR); } if (FinTrig) SetOutput (2, n, 1); else SetOutput (2, n, 0); if (m_Mode==PLAYM) { SetOutput (0, n, m_SampleL[m_Pos] * m_GUIArgs.Volume); SetOutput (1, n, m_SampleR[m_Pos] * m_GUIArgs.Volume); m_Pos += m_GUIArgs.PitchMod + CVPitch; m_GlobalPos += m_GUIArgs.PitchMod + CVPitch; } else { SetOutput (0, n, 0); SetOutput (1, n, 0); } } m_GUIArgs.TimeOut = m_GlobalPos / (float)m_SampleRate; m_GUIArgs.PlayOut = m_Mode==PLAYM; } } void StreamPlugin::ExecuteCommands() { if (m_AudioCH->IsCommandWaiting()) { switch (m_AudioCH->GetCommand()) { case SET_TIME: SetTime(); break; case LOAD: OpenStream(); break; case RESTART: m_StreamPos = 0; m_GlobalPos = 0; break; case STOP: m_Mode = STOPM; break; case PLAY: m_Mode = PLAYM; break; } } } void StreamPlugin::SetTime (void) { m_GlobalPos = m_SampleRate * m_GUIArgs.Time; m_StreamPos = (int)(m_SampleRate * m_GUIArgs.Time); m_Pos = m_SampleSize; } void StreamPlugin::OpenStream (void) { m_StreamPos = 0; m_GlobalPos = 0; if (m_File.IsOpen ()) m_File.Close (); m_File.Open (m_GUIArgs.FileName, WavFile::READ); if (m_File.GetSize() < 256) m_SampleSize = m_File.GetSize(); else m_SampleSize = 256; m_SampleL.Allocate (m_SampleSize); m_SampleR.Allocate (m_SampleSize); m_Pitch = m_SampleRate / (float)m_HostInfo->SAMPLERATE; if (m_File.IsStereo ()) { m_Pitch *= 2; m_GUIArgs.MaxTime = GetLength(); } else m_GUIArgs.MaxTime = GetLength() / 2; } float StreamPlugin::GetLength (void) { if (m_File.IsStereo()) return m_File.GetSize() / (float)m_File.GetSamplerate (); else return m_File.GetSize() / (float)m_File.GetSamplerate () * 2; } void StreamPlugin::StreamOut (ostream &s) { s << m_Version << " " << m_GUIArgs.Volume << " " << m_GUIArgs.PitchMod << " " << strlen (m_GUIArgs.FileName) << " " << m_GUIArgs.FileName << " " // is it really necessary to save this lot?? << m_Pos << " " << m_StreamPos << " " << m_GlobalPos << " " << m_Pitch << " " << endl; } void StreamPlugin::StreamIn(istream &s) { int version; s >> version; s >> m_GUIArgs.Volume >> m_GUIArgs.PitchMod; int size; s >> size; if (size > 255) size = 255; s.ignore (1); s.get (m_GUIArgs.FileName, size+1); if (m_GUIArgs.FileName != "None") OpenStream (); // is it really necessary to load this lot?? s >> m_Pos; s >> m_StreamPos; s >> m_GlobalPos; s >> m_Pitch; }