float* AUD_readSoundBuffer(const char* filename, float low, float high, float attack, float release, float threshold, int accumulate, int additive, int square, float sthreshold, double samplerate, int* length) { AUD_Buffer buffer; AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = (AUD_SampleRate)samplerate; AUD_Reference<AUD_IFactory> sound; AUD_Reference<AUD_IFactory> file = new AUD_FileFactory(filename); AUD_Reference<AUD_IReader> reader = file->createReader(); AUD_SampleRate rate = reader->getSpecs().rate; sound = new AUD_ChannelMapperFactory(file, specs); if(high < rate) sound = new AUD_LowpassFactory(sound, high); if(low > 0) sound = new AUD_HighpassFactory(sound, low); sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f); sound = new AUD_LinearResampleFactory(sound, specs); if(square) sound = new AUD_SquareFactory(sound, sthreshold); if(accumulate) sound = new AUD_AccumulatorFactory(sound, additive); else if(additive) sound = new AUD_SumFactory(sound); reader = sound->createReader(); if(reader.isNull()) return NULL; int len; int position = 0; bool eos; do { len = samplerate; buffer.resize((position + len) * sizeof(float), true); reader->read(len, eos, buffer.getBuffer() + position); position += len; } while(!eos); float* result = (float*)malloc(position * sizeof(float)); memcpy(result, buffer.getBuffer(), position * sizeof(float)); *length = position; return result; }
int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_per_second) { AUD_DeviceSpecs specs; sample_t* buf; AUD_Buffer aBuffer; specs.rate = AUD_RATE_INVALID; specs.channels = AUD_CHANNELS_MONO; specs.format = AUD_FORMAT_INVALID; AUD_Reference<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); specs.specs = reader->getSpecs(); int len; float samplejump = specs.rate / samples_per_second; float min, max, power; bool eos; for(int i = 0; i < length; i++) { len = floor(samplejump * (i+1)) - floor(samplejump * i); aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs)); buf = aBuffer.getBuffer(); reader->read(len, eos, buf); max = min = *buf; power = *buf * *buf; for(int j = 1; j < len; j++) { if(buf[j] < min) min = buf[j]; if(buf[j] > max) max = buf[j]; power += buf[j] * buf[j]; } buffer[i * 3] = min; buffer[i * 3 + 1] = max; buffer[i * 3 + 2] = sqrt(power) / len; if(eos) { length = i; break; } } return length; }
int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer& buffer) { // save packet parameters uint8_t *audio_pkg_data = packet->data; int audio_pkg_size = packet->size; int buf_size = buffer.getSize(); int buf_pos = 0; int read_length, data_size; AVPacket tmp_pkt; av_init_packet(&tmp_pkt); // as long as there is still data in the package while(audio_pkg_size > 0) { // resize buffer if needed if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE) { buffer.resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true); buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE; } // read samples from the packet data_size = buf_size - buf_pos; tmp_pkt.data = audio_pkg_data; tmp_pkt.size = audio_pkg_size; read_length = avcodec_decode_audio3( m_codecCtx, (int16_t*)(((data_t*)buffer.getBuffer()) + buf_pos), &data_size, &tmp_pkt); // read error, next packet! if(read_length < 0) break; buf_pos += data_size; // move packet parameters audio_pkg_data += read_length; audio_pkg_size -= read_length; } return buf_pos; }
void AUD_SoftwareDevice::mix(data_t* buffer, int length) { lock(); { AUD_SoftwareHandle* sound; int len; int pos; sample_t* buf; std::list<AUD_SoftwareHandle*> stopSounds; std::list<AUD_Buffer*> tempBufs; AUD_Buffer* tempbuf; int samplesize = AUD_SAMPLE_SIZE(m_specs); // for all sounds AUD_HandleIterator it = m_playingSounds.begin(); while(it != m_playingSounds.end()) { sound = *it; // increment the iterator to make sure it's valid, // in case the sound gets deleted after stopping ++it; // get the buffer from the source pos = 0; len = length; sound->reader->read(len, buf); // in case of looping while(pos + len < length && sound->loopcount) { tempbuf = new AUD_Buffer(len * samplesize); memcpy(tempbuf->getBuffer(), buf, len * samplesize); tempBufs.push_back(tempbuf); m_mixer->add(tempbuf->getBuffer(), pos, len, sound->volume); pos += len; if(sound->loopcount > 0) sound->loopcount--; sound->reader->seek(0); len = length - pos; sound->reader->read(len, buf); // prevent endless loop if(!len) break; } m_mixer->add(buf, pos, len, sound->volume); pos += len; // in case the end of the sound is reached if(pos < length) { if(sound->stop) sound->stop(sound->stop_data); if(sound->keep) pause(sound); else stopSounds.push_back(sound); } } // superpose m_mixer->superpose(buffer, length, m_volume); // cleanup while(!stopSounds.empty()) { sound = stopSounds.front(); stopSounds.pop_front(); stop(sound); } while(!tempBufs.empty()) { tempbuf = tempBufs.front(); tempBufs.pop_front(); delete tempbuf; } } unlock(); }
int AUD_FFMPEGReader::decode(AVPacket& packet, AUD_Buffer& buffer) { #ifdef FFMPEG_HAVE_DECODE_AUDIO4 AVFrame* frame = NULL; int got_frame; int read_length; uint8_t* orig_data = packet.data; int orig_size = packet.size; int buf_size = buffer.getSize(); int buf_pos = 0; while(packet.size > 0) { got_frame = 0; if(!frame) frame = avcodec_alloc_frame(); else avcodec_get_frame_defaults(frame); read_length = avcodec_decode_audio4(m_codecCtx, frame, &got_frame, &packet); if(read_length < 0) break; if(got_frame) { int data_size = av_samples_get_buffer_size(NULL, m_codecCtx->channels, frame->nb_samples, m_codecCtx->sample_fmt, 1); if(buf_size - buf_pos < data_size) { buffer.resize(buf_size + data_size, true); buf_size += data_size; } if(m_tointerleave) { int single_size = data_size / m_codecCtx->channels / frame->nb_samples; for(int channel = 0; channel < m_codecCtx->channels; channel++) { for(int i = 0; i < frame->nb_samples; i++) { memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size, frame->data[channel] + i * single_size, single_size); } } } else memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[0], data_size); buf_pos += data_size; } packet.size -= read_length; packet.data += read_length; } packet.data = orig_data; packet.size = orig_size; av_free(frame); return buf_pos; #else // save packet parameters uint8_t *audio_pkg_data = packet.data; int audio_pkg_size = packet.size; int buf_size = buffer.getSize(); int buf_pos = 0; int read_length, data_size; AVPacket tmp_pkt; av_init_packet(&tmp_pkt); // as long as there is still data in the package while(audio_pkg_size > 0) { // resize buffer if needed if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE) { buffer.resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true); buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE; } // read samples from the packet data_size = buf_size - buf_pos; tmp_pkt.data = audio_pkg_data; tmp_pkt.size = audio_pkg_size; read_length = avcodec_decode_audio3( m_codecCtx, (int16_t*)(((data_t*)buffer.getBuffer()) + buf_pos), &data_size, &tmp_pkt); // read error, next packet! if(read_length < 0) break; buf_pos += data_size; // move packet parameters audio_pkg_data += read_length; audio_pkg_size -= read_length; } return buf_pos; #endif }