123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /**
- * Copyright (c) 2006-2014 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
- #include "SoundData.h"
- // C
- #include <cstdlib>
- #include <cstring>
- // C++
- #include <limits>
- #include <iostream>
- #include <vector>
- namespace love
- {
- namespace sound
- {
- SoundData::SoundData(Decoder *decoder)
- : data(0)
- , size(0)
- , sampleRate(Decoder::DEFAULT_SAMPLE_RATE)
- , bitDepth(0)
- , channels(0)
- {
- size_t bufferSize = 524288; // 0x80000
- int decoded = decoder->decode();
- while (decoded > 0)
- {
- // Expand or allocate buffer. Note that realloc may move
- // memory to other locations.
- if (!data || bufferSize < size + decoded)
- {
- while (bufferSize < size + decoded)
- bufferSize <<= 1;
- data = (uint8 *) realloc(data, bufferSize);
- }
- if (!data)
- throw love::Exception("Not enough memory.");
- // Copy memory into new part of memory.
- memcpy(data + size, decoder->getBuffer(), decoded);
- // Overflow check.
- if (size > std::numeric_limits<size_t>::max() - decoded)
- {
- free(data);
- throw love::Exception("Not enough memory.");
- }
- // Keep this up to date.
- size += decoded;
- decoded = decoder->decode();
- }
- // Shrink buffer if necessary.
- if (data && bufferSize > size)
- data = (uint8 *) realloc(data, size);
- channels = decoder->getChannels();
- bitDepth = decoder->getBitDepth();
- sampleRate = decoder->getSampleRate();
- }
- SoundData::SoundData(int samples, int sampleRate, int bitDepth, int channels)
- : data(0)
- , size(0)
- , sampleRate(0)
- , bitDepth(0)
- , channels(0)
- {
- load(samples, sampleRate, bitDepth, channels);
- }
- SoundData::SoundData(void *d, int samples, int sampleRate, int bitDepth, int channels)
- : data(0)
- , size(0)
- , sampleRate(0)
- , bitDepth(0)
- , channels(0)
- {
- load(samples, sampleRate, bitDepth, channels, d);
- }
- SoundData::~SoundData()
- {
- if (data != 0)
- free(data);
- }
- void SoundData::load(int samples, int sampleRate, int bitDepth, int channels, void *newData)
- {
- if (samples <= 0)
- throw love::Exception("Invalid sample count: %d", samples);
- if (sampleRate <= 0)
- throw love::Exception("Invalid sample rate: %d", sampleRate);
- if (bitDepth <= 0)
- throw love::Exception("Invalid bit depth: %d", bitDepth);
- if (channels <= 0)
- throw love::Exception("Invalid channel count: %d", channels);
- if (data != 0)
- {
- free(data);
- data = 0;
- }
- size = samples * (bitDepth / 8) * channels;
- this->sampleRate = sampleRate;
- this->bitDepth = bitDepth;
- this->channels = channels;
- double realsize = samples;
- realsize *= (bitDepth / 8) * channels;
- if (realsize > std::numeric_limits<size_t>::max())
- throw love::Exception("Data is too big!");
- data = (uint8 *) malloc(size);
- if (!data)
- throw love::Exception("Not enough memory.");
- if (newData)
- memcpy(data, newData, size);
- else
- memset(data, bitDepth == 8 ? 128 : 0, size);
- }
- void *SoundData::getData() const
- {
- return (void *)data;
- }
- size_t SoundData::getSize() const
- {
- return size;
- }
- int SoundData::getChannels() const
- {
- return channels;
- }
- int SoundData::getBitDepth() const
- {
- return bitDepth;
- }
- int SoundData::getSampleRate() const
- {
- return sampleRate;
- }
- int SoundData::getSampleCount() const
- {
- return (size/channels)/(bitDepth/8);
- }
- float SoundData::getDuration() const
- {
- return float(size) / (channels*sampleRate*bitDepth/8);
- }
- void SoundData::setSample(int i, float sample)
- {
- // Check range.
- if (i < 0 || (size_t) i >= size/(bitDepth/8))
- throw love::Exception("Attempt to set out-of-range sample!");
- if (bitDepth == 16)
- {
- // 16-bit sample values are signed.
- int16 *s = (int16 *) data;
- s[i] = (int16) (sample * (float) LOVE_INT16_MAX);
- }
- else
- {
- // 8-bit sample values are unsigned internally.
- data[i] = (uint8) ((sample * 127.0f) + 128.0f);
- }
- }
- float SoundData::getSample(int i) const
- {
- // Check range.
- if (i < 0 || (size_t) i >= size/(bitDepth/8))
- throw love::Exception("Attempt to get out-of-range sample!");
- if (bitDepth == 16)
- {
- // 16-bit sample values are signed.
- int16 *s = (int16 *) data;
- return (float) s[i] / (float) LOVE_INT16_MAX;
- }
- else
- {
- // 8-bit sample values are unsigned internally.
- return ((float) data[i] - 128.0f) / 127.0f;
- }
- }
- } // sound
- } // love
|