/* SpiralLoops * Copyleft (C) 2000 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 #include "Loop.h" #include "../../RiffWav.h" //#include "SpiralLoopsInfo.h" static const int RECBUFFERSIZE = 16384; static const float RECORD_GAIN = 1.0f; Loop::Loop() : m_Id(0), m_Pos(0), m_IntPos(0), m_PlayBufPos(0), m_Playing(true), m_Recording(false), m_Master(false), m_DelMe(false), m_LoopPoint(0), m_Speed(1.0f), m_Volume(1.0f), m_RecordingSource(NULL), m_Balance(1.0f), m_LeftVol(1.0f), m_RightVol(1.0f), m_FirstRecord(true), m_FixedRecord(false), m_RecLength(0), m_EffectsOn(false) { } Loop::~Loop() { } void Loop::LoadWav(const char *Filename) { WavFile wav; if (wav.Open(Filename, WavFile::READ)) { Clear(); AllocateMem(wav.GetSize()); wav.Load(m_StoreBuffer); //((Fl_Loop*)(m_GUI->GetGUI()))->DrawEveryThing(); m_GUI->UpdateDataPtr(); } } void Loop::SaveWav(const char *Filename) { WavFile wav; if (wav.Open(Filename, WavFile::WRITE, WavFile::MONO)) { wav.Save(m_StoreBuffer); } m_Sample=Filename; } bool Loop::GetOutput(Sample &data) { if (!m_Recording && !m_Playing) { return false; } if (!m_Recording && m_StoreBuffer.GetLength()==0) { return false; } if (m_Recording) { RecordBuf(m_Pos, data.GetLength()); if (!m_StoreBuffer.GetLength()) { return false; } } int Pos; for (int n=0; n(m_Pos); // brute force fix if (Pos>0 && Pos(m_Pos)>=m_LoopPoint) { m_Pos=0; } } m_Filter.GetOutput(0,data); // causes problems if we save to a hold buffer // while we're recording, as we might not know // the size of the final buffer if (!m_Recording) { for (int n=0; n=m_LoopPoint) { m_PlayBufPos=0; } m_HoldBuffer.Set(m_PlayBufPos,data[n]); m_PlayBufPos++; } } m_IntPos=static_cast(m_Pos); m_GUI->UpdatePos(); return true; } void Loop::AllocateMem(int Length) { // We might need to keep these values (if loading workspace) if (m_LoopPoint>Length) m_LoopPoint=Length; if (m_Pos>Length) m_Pos=0; if (m_LoopPoint==0) m_LoopPoint=Length; if (!m_StoreBuffer.Allocate(Length) || !m_HoldBuffer.Allocate(Length)) { cerr<<"AllocateMem can't allocate any more memory!"<=m_StoreBuffer.GetLength()) { Pos=0; } for (int n=0; n(Pos)]+m_RecordingSource[n]*RECORD_GAIN; // fill in all the samples between the speed jump with the same value m_StoreBuffer.Set((int)Pos,temp); for (int i=static_cast(OldPos); i<=static_cast(Pos); i++) { m_StoreBuffer.Set(i,temp); } OldPos=Pos; Pos+=m_Speed; if (Pos>=m_StoreBuffer.GetLength()) { Pos-=m_StoreBuffer.GetLength(); // remember to fill up to the end of the last buffer for (int i=static_cast(OldPos); i=RECBUFFERSIZE) { // put the two buffers together m_StoreBuffer.Add(m_RecBuffer); m_RecPos=0; } long temp=(long)(m_RecordingSource[n]*RECORD_GAIN); m_RecBuffer.Set(m_RecPos,temp); m_RecLength++; m_RecPos++; } } } void Loop::EndRecordBuf() { m_FirstRecord=true; m_LoopPoint=m_StoreBuffer.GetLength(); if (!m_FixedRecord) { // reallocate the hold buffer for the new size // (if the size has changed) m_HoldBuffer.Allocate(m_LoopPoint); } } void Loop::Crop() { if (m_LoopPointLen) { SetLength(Len); return; } else { // if it's empty if (!m_StoreBuffer.GetLength()) { AllocateMem(Len); m_StoreBuffer.Zero(); } else // there is something in the buffer already, but we need to // add on some extra data to make the length the same { int ExtraLen=Len-m_StoreBuffer.GetLength(); m_StoreBuffer.Expand(ExtraLen); m_HoldBuffer.Expand(ExtraLen); } } } void Loop::Cut(int Start, int End) { //m_Parent->Cut(m_StoreBuffer,Start,End); if (m_StoreBuffer.GetLength()m_LoopPoint) { m_Pos=0; } m_HoldBuffer.Allocate(m_StoreBuffer.GetLength()); } void Loop::Copy(int Start, int End) { //m_Parent->Copy(m_StoreBuffer,Start,End); } void Loop::Paste(int Start) { //m_Parent->Paste(m_StoreBuffer,Start); if (m_StoreBuffer.GetLength()m_LoopPoint) { m_Pos=0; } m_HoldBuffer.Allocate(m_StoreBuffer.GetLength()); } void Loop::PasteMix(int Start) { //m_Parent->PasteMix(m_StoreBuffer,Start); } void Loop::ZeroRange(int Start, int End) { for (int n=Start; nm_LoopPoint) { m_Pos=0; } } void Loop::SelectAll() { } void Loop::Move(int Start) { m_StoreBuffer.Move(Start); } void Loop::StreamIn(istream &s) { s>>m_Id>>m_Pos>>m_IntPos>>m_PlayBufPos>>m_Playing>>m_Master>>m_LoopPoint>> m_Speed>>m_Volume>>m_Balance>>m_LeftVol>>m_RightVol>>m_Filter>> m_EffectsOn; } void Loop::StreamOut(ostream &s) { s<>(istream &s, Loop &o) { s>>o.m_Id>>o.m_Pos>>o.m_IntPos>>o.m_PlayBufPos>>o.m_Playing>>o.m_Master>>o.m_LoopPoint>> o.m_Speed>>o.m_Volume>>o.m_Balance>>o.m_LeftVol>>o.m_RightVol>>o.m_Filter>> o.m_EffectsOn; char Buf[4096]; int size; s>>size; s.ignore(1); s.get(Buf,size+1); o.m_Sample=Buf; if (o.m_Sample!="") { o.LoadWav(o.m_Sample.c_str()); } return s; } ostream &operator<<(ostream &s, Loop &o) { // if this sample is not saved, get the user to pick a filename. if (o.m_Sample=="") { char *fn=fl_file_chooser("Save loop as Wav file", "*.wav", NULL); if (fn && fn!="") { o.m_Sample=fn; o.SaveWav(o.m_Sample.c_str()); } } else { if (fl_ask("Save loop sample %s?",o.m_Sample.c_str())) { o.SaveWav(o.m_Sample.c_str()); } } s<