mirror of
https://github.com/reactos/reactos.git
synced 2024-11-06 06:33:08 +00:00
236 lines
5.6 KiB
C++
236 lines
5.6 KiB
C++
/* PROJECT: ReactOS sndrec32
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/applications/sndrec32/audio_membuffer.cpp
|
|
* PURPOSE: Sound recording
|
|
* PROGRAMMERS: Marco Pagliaricci (irc: rendar)
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "audio_membuffer.hpp"
|
|
|
|
_AUDIO_NAMESPACE_START_
|
|
|
|
/* Protected Functions */
|
|
|
|
void
|
|
audio_membuffer::alloc_mem_(unsigned int bytes)
|
|
{
|
|
/* Some checking */
|
|
if (bytes == 0)
|
|
return;
|
|
|
|
/* Checks previously alloc'd memory and frees it */
|
|
if (audio_data)
|
|
delete[] audio_data;
|
|
|
|
/* Allocs new memory and zeros it */
|
|
audio_data = new BYTE[bytes];
|
|
memset(audio_data, 0, bytes * sizeof(BYTE));
|
|
|
|
/* Sets the correct buffer size */
|
|
buf_size = bytes;
|
|
init_size = bytes;
|
|
}
|
|
|
|
void
|
|
audio_membuffer::free_mem_(void)
|
|
{
|
|
if (audio_data)
|
|
delete[] audio_data;
|
|
|
|
buf_size = 0;
|
|
audio_data = 0;
|
|
}
|
|
|
|
void
|
|
audio_membuffer::resize_mem_(unsigned int new_size)
|
|
{
|
|
if (new_size == 0)
|
|
return;
|
|
|
|
/* The new_size, cannot be <= of the `bytes_received' member value of the
|
|
parent class `audio_receiver'. We cannot touch received audio data,
|
|
so we have to alloc at least bytes_received+1 bytes. But we can truncate
|
|
unused memory, so `new_size' can be < of `buf_size' */
|
|
if (new_size <= bytes_received)
|
|
return;
|
|
|
|
BYTE * new_mem;
|
|
|
|
/* Allocs new memory and zeros it */
|
|
new_mem = new BYTE[new_size];
|
|
memset(new_mem, 0, new_size * sizeof(BYTE));
|
|
|
|
if (audio_data)
|
|
{
|
|
/* Copies received audio data, and discard unused memory */
|
|
memcpy(new_mem, audio_data, bytes_received);
|
|
/* Frees old memory */
|
|
delete[] audio_data;
|
|
/* Commit new memory */
|
|
audio_data = new_mem;
|
|
buf_size = new_size;
|
|
} else {
|
|
audio_data = new_mem;
|
|
buf_size = new_size;
|
|
}
|
|
|
|
if (buffer_resized)
|
|
buffer_resized(new_size);
|
|
}
|
|
|
|
void
|
|
audio_membuffer::truncate_(void)
|
|
{
|
|
/* If `buf_size' is already = to the `bytes_received' of audio data,
|
|
then this operation is useless; simply return */
|
|
if (bytes_received == buf_size)
|
|
return;
|
|
|
|
if (audio_data)
|
|
{
|
|
/* Allocs a new buffer */
|
|
BYTE * newbuf = new BYTE[bytes_received];
|
|
/* Copies audio data */
|
|
memcpy(newbuf, audio_data, bytes_received);
|
|
/* Frees old memory */
|
|
delete[] audio_data;
|
|
/* Commit the new buffer */
|
|
audio_data = newbuf;
|
|
buf_size = bytes_received;
|
|
|
|
/* Buffer truncation successful. Now the buffer size is exactly big
|
|
as much audio data was received */
|
|
}
|
|
}
|
|
|
|
/* Public Functions */
|
|
|
|
void
|
|
audio_membuffer::clear(void)
|
|
{
|
|
free_mem_();
|
|
bytes_received = 0;
|
|
}
|
|
|
|
void
|
|
audio_membuffer::reset(void)
|
|
{
|
|
/* Frees memory and reset to initial state */
|
|
clear();
|
|
/* Alloc memory of size specified at the constructor */
|
|
alloc_mem_(init_size);
|
|
}
|
|
|
|
void
|
|
audio_membuffer::alloc_bytes(unsigned int bytes)
|
|
{
|
|
alloc_mem_(bytes);
|
|
}
|
|
|
|
void
|
|
audio_membuffer::alloc_seconds(unsigned int secs)
|
|
{
|
|
alloc_mem_(aud_info.byte_rate() * secs);
|
|
}
|
|
|
|
void
|
|
audio_membuffer::alloc_seconds(float secs)
|
|
{
|
|
alloc_mem_((unsigned int)((float)aud_info.byte_rate() * secs));
|
|
}
|
|
|
|
void
|
|
audio_membuffer::resize_bytes(unsigned int bytes)
|
|
{
|
|
resize_mem_(bytes);
|
|
}
|
|
|
|
void
|
|
audio_membuffer::resize_seconds(unsigned int secs)
|
|
{
|
|
resize_mem_(aud_info.byte_rate() * secs);
|
|
}
|
|
|
|
void
|
|
audio_membuffer::resize_seconds(float secs)
|
|
{
|
|
resize_mem_((unsigned int)((float)aud_info.byte_rate() * secs));
|
|
}
|
|
|
|
/* Inherited Functions */
|
|
|
|
void
|
|
audio_membuffer::audio_receive(unsigned char *data, unsigned int size)
|
|
{
|
|
/* If there isn't a buffer, allocs memory for it of size*2, and copies audio data arrival */
|
|
if ((audio_data == 0) || (buf_size == 0))
|
|
{
|
|
alloc_mem_(size * 2);
|
|
memcpy(audio_data, data, size);
|
|
return;
|
|
}
|
|
|
|
/* If buffer's free memory is < of `size', we have to realloc buffer memory
|
|
of buf_size*2, while free memory is enough to contain `size' bytes.
|
|
In this case free memory is represented by `buf_size - bytes_recorded' */
|
|
unsigned int tot_mem = buf_size, free_mem = buf_size - bytes_received;
|
|
if (free_mem < size)
|
|
{
|
|
/* Calcs new buffer size */
|
|
/* TODO: flags for other behaviour? */
|
|
while (free_mem < size)
|
|
{
|
|
tot_mem *= 2;
|
|
free_mem = tot_mem - bytes_received;
|
|
}
|
|
|
|
/* Resize buffer memory */
|
|
resize_mem_(tot_mem);
|
|
}
|
|
|
|
/* Now we have enough free space in the buffer, so let's copy audio data arrivals */
|
|
memcpy(audio_data + bytes_received, data, size);
|
|
|
|
if (audio_arrival)
|
|
audio_arrival(aud_info.samples_in_bytes(size));
|
|
}
|
|
|
|
unsigned int
|
|
audio_membuffer::read(BYTE *out_buf, unsigned int bytes)
|
|
{
|
|
/* Some checking */
|
|
if (!audio_data)
|
|
return 0;
|
|
|
|
if (bytes_played_ >= bytes_received)
|
|
return 0;
|
|
|
|
unsigned int to_play = bytes_received - bytes_played_;
|
|
unsigned int to_copy = bytes > to_play ? to_play : bytes;
|
|
|
|
/* Copies the audio data out */
|
|
if ((out_buf) && (to_copy) && (audio_data))
|
|
memcpy(out_buf, audio_data + bytes_played_, to_copy);
|
|
|
|
/* Increments the number of total bytes played (audio data gone out from
|
|
the `audio_producer' object) */
|
|
bytes_played_ += to_copy;
|
|
|
|
if (audio_arrival)
|
|
audio_arrival(aud_info.samples_in_bytes(to_copy));
|
|
|
|
/* Returns the exact size of audio data produced */
|
|
return to_copy;
|
|
}
|
|
|
|
bool
|
|
audio_membuffer::finished(void)
|
|
{
|
|
if (bytes_played_ < bytes_received)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
_AUDIO_NAMESPACE_END_
|