/* 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 "Loop.h" #include "SpiralSound/RiffWav.h" #include "SpiralLoopsInfo.h" static const int RECBUFFERSIZE = 16384; static const float RECORD_GAIN = 1.0f; Loop::Loop(Loops *s) : 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), m_Parent(s) { m_Delay.SetNumChannels(1); m_Reverb.SetNumChannels(1); } Loop::~Loop() { } void Loop::LoadWav(char *Filename) { WavFile wav; if (wav.Open(Filename, WavFile::READ)) { Clear(); AllocateMem(wav.GetSize()); wav.Load(m_StoreBuffer); } } void Loop::SaveWav(char *Filename) { WavFile wav; if (wav.Open(Filename, WavFile::WRITE, WavFile::MONO)) { wav.Save(m_StoreBuffer); } } 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); if (!m_StoreBuffer.GetLength()) { return false; } } int Pos; for (int n=0; n(m_Pos); // brute force fix if (Pos>0 && Pos(m_StoreBuffer[Pos]*m_Volume); } else data[n]=0; m_Pos+=m_Speed; if (static_cast(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[m_PlayBufPos]=data[n]; m_PlayBufPos++; } } // Run the effects if (m_EffectsOn) { m_Delay.GetOutput(data); m_Reverb.GetOutput(data); } 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; } float OldPos=Pos; for (int n=0; n(Pos)]+m_RecordingSource[n]*RECORD_GAIN); // todo: fill in all the samples between the // speed jump with the same value 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=OldPos=0; } } } else { for (int n=0; n=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); } istream &operator>>(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>>o.m_Delay>>o.m_Reverb; return s; } ostream &operator<<(ostream &s, Loop &o) { s<