1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
* FILE: transcoder.c
* PROGRAM: Rat
* AUTHOR: Colin Perkins
*
* Based on auddev_mux.c, revision 1.11
*
* Copyright (C) 1996-2001 University College London
* All rights reserved.
*/
#ifndef HIDE_SOURCE_STRINGS
static const char cvsid[] =
"$Id: transcoder.c,v 1.13 2001/01/08 20:30:11 ucaccsp Exp $";
#endif /* HIDE_SOURCE_STRINGS */
#include "config_unix.h"
#include "config_win32.h"
#include "memory.h"
#include "audio_types.h"
#include "transcoder.h"
#define CHANNEL_SIZE 8192
#define NUM_CHANNELS 2
static int num_open_channels = 0;
static sample *channel[NUM_CHANNELS+1];
static int head[NUM_CHANNELS+1];
static int tail[NUM_CHANNELS+1];
static struct timeval last_time[NUM_CHANNELS+1];
static struct timeval curr_time[NUM_CHANNELS+1];
static int first_time[NUM_CHANNELS+1];
int
transcoder_open(void)
{
/* Open a fake audio channel. The value we return is used to identify the */
/* channel for the other routines in this module. The #ifdefs in net.c */
/* prevent it being used in a select(). */
/* Note: We must open EXACTLY two channels, before the other routines in */
/* this module function correctly. */
int id, i;
assert((num_open_channels >= 0) && (num_open_channels < NUM_CHANNELS));
id = ++num_open_channels;
head[id] = 0;
tail[id] = 0;
first_time[id] = 0;
channel[id] = (sample *) xmalloc(CHANNEL_SIZE * sizeof(sample));
for (i=0; i<CHANNEL_SIZE; i++) {
channel[id][i] = L16_AUDIO_ZERO;
}
return id;
}
void
transcoder_close(int id)
{
assert(num_open_channels > 0);
assert(id > 0 && id <= num_open_channels);
xfree(channel[id]);
num_open_channels--;
}
int
transcoder_read(int id, sample *buf, int buf_size)
{
int i, read_size, copy_size;
assert(buf != 0);
assert(buf_size > 0);
assert(id > 0 && id <= num_open_channels);
assert(head[id] <= CHANNEL_SIZE);
assert(tail[id] <= CHANNEL_SIZE);
assert(head[id] <= tail[id]);
if (first_time[id] == 0) {
gettimeofday(&last_time[id], NULL);
first_time[id] = 1;
}
gettimeofday(&curr_time[id], NULL);
read_size = (((curr_time[id].tv_sec - last_time[id].tv_sec) * 1000000) + (curr_time[id].tv_usec - last_time[id].tv_usec)) / 125;
if (read_size > buf_size) read_size = buf_size;
for (i=0; i<read_size; i++) {
buf[i] = L16_AUDIO_ZERO;
}
last_time[id] = curr_time[id];
copy_size = tail[id] - head[id]; /* The amount of data available in this module... */
if (copy_size >= read_size) {
copy_size = read_size;
} else {
#ifdef DEBUG_TRANSCODER
printf("transcoder_read: underflow, silence substituted -- want %d got %d channel %d\n", read_size, copy_size, id);
#endif
}
assert((head[id] + copy_size) <= tail[id]);
for (i=0; i<copy_size; i++) {
buf[i] = channel[id][head[id] + i];
}
head[id] += copy_size;
assert(head[id] <= CHANNEL_SIZE);
assert(tail[id] <= CHANNEL_SIZE);
assert(head[id] <= tail[id]);
return read_size;
}
int
transcoder_write(int id, sample *buf, int buf_size)
{
int i;
assert(buf != 0);
assert(buf_size > 0);
assert(id > 0 && id <= num_open_channels);
assert(head[id] <= CHANNEL_SIZE);
assert(tail[id] <= CHANNEL_SIZE);
assert(head[id] <= tail[id]);
if ((tail[id] + buf_size) > CHANNEL_SIZE) {
for (i=0; i < (CHANNEL_SIZE - head[id]); i++) {
channel[id][i] = channel[id][i + head[id]];
}
tail[id] -= head[id];
head[id] = 0;
}
assert((tail[id] + buf_size) <= CHANNEL_SIZE);
for (i=0; i<buf_size; i++) {
channel[id][tail[id] + i] = buf[i];
}
tail[id] += buf_size;
assert(head[id] <= CHANNEL_SIZE);
assert(tail[id] <= CHANNEL_SIZE);
assert(head[id] <= tail[id]);
return buf_size;
}
|