diff --git a/src/modules/sound/SoundData.cpp b/src/modules/sound/SoundData.cpp index 258f605bc..9b81044e0 100644 --- a/src/modules/sound/SoundData.cpp +++ b/src/modules/sound/SoundData.cpp @@ -258,5 +258,32 @@ float SoundData::getSample(int i, int channel) const return getSample(i * channels + (channel - 1)); } +void SoundData::copyFrom(const SoundData *src, int srcStart, int count, int dstStart) +{ + if (channels != src->channels) + throw love::Exception("Channel count mismatch!"); + + size_t bytesPerSample = (size_t) channels * bitDepth/8; + size_t srcBytesPerSample = (size_t) src->channels * src->bitDepth/8; + + // Check range + if (dstStart < 0 || (dstStart+count) * bytesPerSample >= size) + throw love::Exception("Destination out-of-range!"); + if (srcStart < 0 || (srcStart+count) * srcBytesPerSample >= src->size) + throw love::Exception("Source out-of-range!"); + + if (bitDepth != src->bitDepth) + { + // Bit depth mismatch, use get/setSample at loop + for (int i = 0; i < count * channels; i++) + setSample(dstStart + i, src->getSample(srcStart + i)); + } + else if (this->data == src->data) + // May overlap, use memmove + memmove(data + dstStart * bytesPerSample, src->data + srcStart * bytesPerSample, count * bytesPerSample); + else + memcpy(data + dstStart * bytesPerSample, src->data + srcStart * bytesPerSample, count * bytesPerSample); +} + } // sound } // love diff --git a/src/modules/sound/SoundData.h b/src/modules/sound/SoundData.h index ba8105a82..431d18247 100644 --- a/src/modules/sound/SoundData.h +++ b/src/modules/sound/SoundData.h @@ -61,6 +61,8 @@ public: float getSample(int i) const; float getSample(int i, int channel) const; + void copyFrom(const SoundData *src, int srcStart, int count, int dstStart); + private: void load(int samples, int sampleRate, int bitDepth, int channels, void *newData = 0); diff --git a/src/modules/sound/wrap_SoundData.cpp b/src/modules/sound/wrap_SoundData.cpp index 86fc7841b..5674ec681 100644 --- a/src/modules/sound/wrap_SoundData.cpp +++ b/src/modules/sound/wrap_SoundData.cpp @@ -121,6 +121,19 @@ int w_SoundData_getSample(lua_State *L) return 1; } +int w_SoundData_copyFrom(lua_State *L) +{ + SoundData *dst = luax_checksounddata(L, 1); + const SoundData *src = luax_checksounddata(L, 2); + + int srcStart = (int) luaL_checkinteger(L, 3); + int count = (int) luaL_checkinteger(L, 4); + int dstStart = (int) luaL_optinteger(L, 5, 0); + + luax_catchexcept(L, [&](){ dst->copyFrom(src, srcStart, count, dstStart); }); + return 0; +} + static const luaL_Reg w_SoundData_functions[] = { { "clone", w_SoundData_clone }, @@ -131,6 +144,7 @@ static const luaL_Reg w_SoundData_functions[] = { "getDuration", w_SoundData_getDuration }, { "setSample", w_SoundData_setSample }, { "getSample", w_SoundData_getSample }, + { "copyFrom", w_SoundData_copyFrom }, { 0, 0 } };