home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek 6
/
Geek-006.iso
/
linux
/
video
/
xmovie-1.5.3.tar.gz
/
xmovie-1.5.3.tar
/
xmovie-1.5.3
/
xmovie
/
audiodevice.C
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-29
|
5KB
|
247 lines
#include "asset.h"
#include "audiodevice.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#ifndef OTHERAUDIO
#include <sys/soundcard.h>
#endif
#include <unistd.h>
AudioDevice::AudioDevice(Asset *asset) : Thread()
{
this->asset = asset;
software_sync = 0;
total_samples_written = 0;
last_samples_written = 0;
playing_back = 0;
last_position = 0;
}
AudioDevice::~AudioDevice()
{
}
int AudioDevice::set_software_sync(int value)
{
this->software_sync = value;
return 0;
}
long AudioDevice::get_fmt()
{
#ifndef OTHERAUDIO
return AFMT_S16_LE;
#endif
return 0;
}
int AudioDevice::start_playback()
{
int format = get_fmt();
timer.update();
actual_buffer = 65536;
#ifndef OTHERAUDIO
audio_buf_info playinfo;
dsp_out = open("/dev/dsp", O_WRONLY);
if(dsp_out < 0)
{
printf("open odevice failed\n");
software_sync = 1;
}
else
{
if(ioctl(dsp_out, SNDCTL_DSP_SETFMT, &format) < 0) printf("SNDCTL_DSP_SETFMT failed\n");
if(ioctl(dsp_out, SNDCTL_DSP_CHANNELS, &asset->channels) < 0) printf("SNDCTL_DSP_CHANNELS failed\n");
if(ioctl(dsp_out, SNDCTL_DSP_SPEED, &asset->rate) < 0) printf("SNDCTL_DSP_SPEED failed\n");
ioctl(dsp_out, SNDCTL_DSP_GETOSPACE, &playinfo);
actual_buffer = playinfo.bytes / (asset->bits / 8) / asset->channels;
}
#endif
for(int i = 0; i < TOTAL_BUFFERS; i++)
{
output_lock[i].lock();
output_buffers[i] = 0;
buffer_len[i] = 0;
}
Thread::synchronous = 1;
playing_back = 1;
last_position = 0;
current_inbuffer = 0;
current_outbuffer = 0;
done = 0;
start();
return actual_buffer;
}
int AudioDevice::interrupt_playback()
{
if(playing_back)
{
done = 1;
Thread::end();
for(int i = 0; i < TOTAL_BUFFERS; i++)
input_lock[i].unlock();
}
return 0;
}
int AudioDevice::stop_playback()
{
Thread::join();
reset();
playing_back = 0;
return 0;
}
int AudioDevice::reset()
{
#ifndef OTHERAUDIO
ioctl(dsp_out, SNDCTL_DSP_RESET, 0);
close(dsp_out);
#endif
for(int i = 0; i < TOTAL_BUFFERS; i++)
{
if(output_buffers[i]) delete output_buffers[i];
output_buffers[i] = 0;
}
return 0;
}
long AudioDevice::samples_rendered()
{
static long result;
#ifndef OTHERAUDIO
count_info info;
#endif
if(playing_back)
{
if(software_sync)
{
timer_lock.lock();
result = total_samples_written - last_samples_written -
actual_buffer;
result += timer.get_scaled_difference(asset->rate);
//printf("AudioDevice::samples_rendered %ld - %ld - %ld + %ld = %ld\n", total_samples_written, last_samples_written, actual_buffer, timer.get_scaled_difference(asset->rate), result);
if(result < 0) result = 0;
timer_lock.unlock();
if(result < last_position)
result = last_position;
else
last_position = result;
return result;
}
else
{
#ifndef OTHERAUDIO
if(!ioctl(dsp_out, SNDCTL_DSP_GETOPTR, &info))
{
result = info.bytes / (asset->bits / 8) / asset->channels;
return result;
}
return 0;
#endif
}
}
else
return total_samples_written;
}
int AudioDevice::write_audio(char *buffer, long samples)
{
if(done) return 1;
input_lock[current_inbuffer].lock();
if(done) return 1;
long bytes = samples_to_bytes(samples);
allocate_buffer(current_inbuffer, samples);
buffer_len[current_inbuffer] = samples;
if(buffer)
{
for(int i = 0; i < bytes; i++)
{
output_buffers[current_inbuffer][i] = buffer[i];
}
}
output_lock[current_inbuffer].unlock();
current_inbuffer = next_buffer(current_inbuffer);
return 0;
}
void AudioDevice::run()
{
while(!done && playing_back)
{
output_lock[current_outbuffer].lock();
if(buffer_len[current_outbuffer] && !done)
{
total_samples_written += buffer_len[current_outbuffer];
last_samples_written = buffer_len[current_outbuffer];
timer_lock.lock();
timer.update();
timer_lock.unlock();
#ifndef OTHERAUDIO
if(write(dsp_out, output_buffers[current_outbuffer],
samples_to_bytes(buffer_len[current_outbuffer])) < 0)
sleep(1);
#else
sleep(1);
#endif
}
else
done = 1; // No more buffers
input_lock[current_outbuffer].unlock();
current_outbuffer = next_buffer(current_outbuffer);
}
#ifndef OTHERAUDIO
ioctl(dsp_out, SNDCTL_DSP_SYNC, 0);
#endif
}
int AudioDevice::next_buffer(int buffer_num)
{
buffer_num++;
if(buffer_num == TOTAL_BUFFERS) buffer_num = 0;
return buffer_num;
}
int AudioDevice::allocate_buffer(int buffer_num, long size)
{
if(size > buffer_len[buffer_num] && output_buffers[buffer_num])
{
delete output_buffers[buffer_num];
output_buffers[buffer_num] = 0;
}
if(!output_buffers[buffer_num])
{
output_buffers[buffer_num] = new char[samples_to_bytes(size)];
}
return 0;
}
long AudioDevice::samples_to_bytes(long samples)
{
return samples * asset->bits / 8 * asset->channels;
}