Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * Copyright 2009-2011 Jörg Hermann Müller 00005 * 00006 * This file is part of AudaSpace. 00007 * 00008 * Audaspace is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * AudaSpace is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with Audaspace; if not, write to the Free Software Foundation, 00020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00030 #include "AUD_LinearResampleReader.h" 00031 00032 #include <cmath> 00033 #include <cstring> 00034 00035 #define CC m_channels + channel 00036 00037 AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, 00038 AUD_Specs specs) : 00039 AUD_ResampleReader(reader, specs.rate), 00040 m_channels(reader->getSpecs().channels), 00041 m_cache_pos(0), 00042 m_cache_ok(false) 00043 { 00044 specs.channels = m_channels; 00045 m_cache.resize(2 * AUD_SAMPLE_SIZE(specs)); 00046 } 00047 00048 void AUD_LinearResampleReader::seek(int position) 00049 { 00050 position = floor(position * double(m_reader->getSpecs().rate) / double(m_rate)); 00051 m_reader->seek(position); 00052 m_cache_ok = false; 00053 m_cache_pos = 0; 00054 } 00055 00056 int AUD_LinearResampleReader::getLength() const 00057 { 00058 return floor(m_reader->getLength() * double(m_rate) / double(m_reader->getSpecs().rate)); 00059 } 00060 00061 int AUD_LinearResampleReader::getPosition() const 00062 { 00063 return floor((m_reader->getPosition() + (m_cache_ok ? m_cache_pos - 1 : 0)) 00064 * m_rate / m_reader->getSpecs().rate); 00065 } 00066 00067 AUD_Specs AUD_LinearResampleReader::getSpecs() const 00068 { 00069 AUD_Specs specs = m_reader->getSpecs(); 00070 specs.rate = m_rate; 00071 return specs; 00072 } 00073 00074 void AUD_LinearResampleReader::read(int& length, bool& eos, sample_t* buffer) 00075 { 00076 if(length == 0) 00077 return; 00078 00079 AUD_Specs specs = m_reader->getSpecs(); 00080 00081 int samplesize = AUD_SAMPLE_SIZE(specs); 00082 int size = length; 00083 float factor = m_rate / m_reader->getSpecs().rate; 00084 float spos; 00085 sample_t low, high; 00086 eos = false; 00087 00088 // check for channels changed 00089 00090 if(specs.channels != m_channels) 00091 { 00092 m_cache.resize(2 * samplesize); 00093 m_channels = specs.channels; 00094 m_cache_ok = false; 00095 } 00096 00097 if(factor == 1 && (!m_cache_ok || m_cache_pos == 1)) 00098 { 00099 // can read directly! 00100 m_reader->read(length, eos, buffer); 00101 00102 if(length > 0) 00103 { 00104 memcpy(m_cache.getBuffer() + m_channels, buffer + m_channels * (length - 1), samplesize); 00105 m_cache_pos = 1; 00106 m_cache_ok = true; 00107 } 00108 00109 return; 00110 } 00111 00112 int len; 00113 sample_t* buf; 00114 00115 if(m_cache_ok) 00116 { 00117 int need = ceil(length / factor + m_cache_pos) - 1; 00118 00119 len = need; 00120 00121 m_buffer.assureSize((len + 2) * samplesize); 00122 buf = m_buffer.getBuffer(); 00123 00124 memcpy(buf, m_cache.getBuffer(), 2 * samplesize); 00125 m_reader->read(len, eos, buf + 2 * m_channels); 00126 00127 if(len < need) 00128 length = floor((len + 1 - m_cache_pos) * factor); 00129 } 00130 else 00131 { 00132 m_cache_pos = 1 - 1 / factor; 00133 00134 int need = ceil(length / factor + m_cache_pos); 00135 00136 len = need; 00137 00138 m_buffer.assureSize((len + 1) * samplesize); 00139 buf = m_buffer.getBuffer(); 00140 00141 memset(buf, 0, samplesize); 00142 m_reader->read(len, eos, buf + m_channels); 00143 00144 if(len == 0) 00145 { 00146 length = 0; 00147 return; 00148 } 00149 00150 if(len < need) 00151 { 00152 length = floor((len - m_cache_pos) * factor); 00153 } 00154 00155 m_cache_ok = true; 00156 } 00157 00158 if(length == 0) 00159 return; 00160 00161 for(int channel = 0; channel < m_channels; channel++) 00162 { 00163 for(int i = 0; i < length; i++) 00164 { 00165 spos = (i + 1) / factor + m_cache_pos; 00166 00167 low = buf[(int)floor(spos) * CC]; 00168 high = buf[(int)ceil(spos) * CC]; 00169 00170 buffer[i * CC] = low + (spos - floor(spos)) * (high - low); 00171 } 00172 } 00173 00174 if(floor(spos) == spos) 00175 { 00176 memcpy(m_cache.getBuffer() + m_channels, buf + int(floor(spos)) * m_channels, samplesize); 00177 m_cache_pos = 1; 00178 } 00179 else 00180 { 00181 memcpy(m_cache.getBuffer(), buf + int(floor(spos)) * m_channels, 2 * samplesize); 00182 m_cache_pos = spos - floor(spos); 00183 } 00184 00185 eos &= length < size; 00186 }