Blender  V2.59
AUD_SequencerReader.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: AUD_SequencerReader.cpp 36092 2011-04-10 22:40:37Z nexyon $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * Copyright 2009-2011 Jörg Hermann Müller
00007  *
00008  * This file is part of AudaSpace.
00009  *
00010  * Audaspace is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * AudaSpace is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with Audaspace; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include "AUD_SequencerReader.h"
00033 #include "AUD_DefaultMixer.h"
00034 
00035 #include <math.h>
00036 
00037 typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator;
00038 typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator;
00039 
00040 AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory,
00041                         std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs,
00042                         void* data, AUD_volumeFunction volume)
00043 {
00044         AUD_DeviceSpecs dspecs;
00045         dspecs.specs = specs;
00046         dspecs.format = AUD_FORMAT_FLOAT32;
00047 
00048         m_mixer = new AUD_DefaultMixer(dspecs);
00049         m_factory = factory;
00050         m_data = data;
00051         m_volume = volume;
00052 
00053         AUD_SequencerStrip* strip;
00054 
00055         for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++)
00056         {
00057                 strip = new AUD_SequencerStrip;
00058                 strip->entry = *i;
00059                 strip->old_sound = NULL;
00060 
00061                 if(strip->old_sound)
00062                         strip->reader = m_mixer->prepare(strip->old_sound->createReader());
00063                 else
00064                         strip->reader = NULL;
00065 
00066                 m_strips.push_front(strip);
00067         }
00068 
00069         m_position = 0;
00070 }
00071 
00072 AUD_SequencerReader::~AUD_SequencerReader()
00073 {
00074         if(m_factory != NULL)
00075                 m_factory->removeReader(this);
00076 
00077         AUD_SequencerStrip* strip;
00078 
00079         while(!m_strips.empty())
00080         {
00081                 strip = m_strips.front();
00082                 m_strips.pop_front();
00083                 if(strip->reader)
00084                 {
00085                         delete strip->reader;
00086                 }
00087                 delete strip;
00088         }
00089 
00090         delete m_mixer;
00091 }
00092 
00093 void AUD_SequencerReader::destroy()
00094 {
00095         m_factory = NULL;
00096         AUD_SequencerStrip* strip;
00097 
00098         while(!m_strips.empty())
00099         {
00100                 strip = m_strips.front();
00101                 m_strips.pop_front();
00102                 delete strip;
00103         }
00104 }
00105 
00106 void AUD_SequencerReader::add(AUD_SequencerEntry* entry)
00107 {
00108         AUD_SequencerStrip* strip = new AUD_SequencerStrip;
00109         strip->entry = entry;
00110 
00111         if(*strip->entry->sound)
00112         {
00113                 strip->old_sound = *strip->entry->sound;
00114                 strip->reader = m_mixer->prepare(strip->old_sound->createReader());
00115         }
00116         else
00117         {
00118                 strip->reader = NULL;
00119                 strip->old_sound = NULL;
00120         }
00121         m_strips.push_front(strip);
00122 }
00123 
00124 void AUD_SequencerReader::remove(AUD_SequencerEntry* entry)
00125 {
00126         AUD_SequencerStrip* strip;
00127         for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
00128         {
00129                 strip = *i;
00130                 if(strip->entry == entry)
00131                 {
00132                         i++;
00133                         if(strip->reader)
00134                         {
00135                                 delete strip->reader;
00136                         }
00137                         m_strips.remove(strip);
00138                         delete strip;
00139                         return;
00140                 }
00141         }
00142 }
00143 
00144 bool AUD_SequencerReader::isSeekable() const
00145 {
00146         return true;
00147 }
00148 
00149 void AUD_SequencerReader::seek(int position)
00150 {
00151         m_position = position;
00152 }
00153 
00154 int AUD_SequencerReader::getLength() const
00155 {
00156         return -1;
00157 }
00158 
00159 int AUD_SequencerReader::getPosition() const
00160 {
00161         return m_position;
00162 }
00163 
00164 AUD_Specs AUD_SequencerReader::getSpecs() const
00165 {
00166         return m_mixer->getSpecs().specs;
00167 }
00168 
00169 void AUD_SequencerReader::read(int & length, sample_t* & buffer)
00170 {
00171         AUD_DeviceSpecs specs = m_mixer->getSpecs();
00172         int samplesize = AUD_SAMPLE_SIZE(specs);
00173         int rate = specs.rate;
00174 
00175         int size = length * samplesize;
00176 
00177         int start, end, current, skip, len;
00178         AUD_SequencerStrip* strip;
00179         sample_t* buf;
00180 
00181         if(m_buffer.getSize() < size)
00182                 m_buffer.resize(size);
00183         buffer = m_buffer.getBuffer();
00184 
00185         if(!m_factory->getMute())
00186         {
00187                 for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
00188                 {
00189                         strip = *i;
00190                         if(!strip->entry->muted)
00191                         {
00192                                 if(strip->old_sound != *strip->entry->sound)
00193                                 {
00194                                         strip->old_sound = *strip->entry->sound;
00195                                         if(strip->reader)
00196                                                 delete strip->reader;
00197 
00198                                         if(strip->old_sound)
00199                                         {
00200                                                 try
00201                                                 {
00202                                                         strip->reader = m_mixer->prepare(strip->old_sound->createReader());
00203                                                 }
00204                                                 catch(AUD_Exception)
00205                                                 {
00206                                                         strip->reader = NULL;
00207                                                 }
00208                                         }
00209                                         else
00210                                                 strip->reader = NULL;
00211                                 }
00212 
00213                                 if(strip->reader)
00214                                 {
00215                                         end = floor(strip->entry->end * rate);
00216                                         if(m_position < end)
00217                                         {
00218                                                 start = floor(strip->entry->begin * rate);
00219                                                 if(m_position + length > start)
00220                                                 {
00221                                                         current = m_position - start;
00222                                                         if(current < 0)
00223                                                         {
00224                                                                 skip = -current;
00225                                                                 current = 0;
00226                                                         }
00227                                                         else
00228                                                                 skip = 0;
00229                                                         current += strip->entry->skip * rate;
00230                                                         len = length > end - m_position ? end - m_position : length;
00231                                                         len -= skip;
00232                                                         if(strip->reader->getPosition() != current)
00233                                                                 strip->reader->seek(current);
00234                                                         strip->reader->read(len, buf);
00235                                                         m_mixer->add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
00236                                                 }
00237                                         }
00238                                 }
00239                         }
00240                 }
00241         }
00242 
00243         m_mixer->superpose((data_t*)buffer, length, 1.0f);
00244 
00245         m_position += length;
00246 }