home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wvis0626.zip
/
warpvision_20020626.zip
/
audio
/
adecode.c
next >
Wrap
C/C++ Source or Header
|
2002-06-19
|
12KB
|
479 lines
/*
* WarpVision audio
*
* Copyleft Alex Strelnikov.
*
* WarpVision is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* WarpVision is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define INCL_DOS
#include <os2.h>
#include <os2me.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys\types.h>
#include <inttypes.h>
#include "avcodec.h"
#include "avifmt.h"
#include "stream.h"
#include "demuxer.h"
#include "stheader.h"
#include "codecs.h"
#include "dart.h"
#include "adecode.h"
#include <mp3.h>
#include <a52.h>
sample_t *a52_data;
a52_state_t *a52_state;
static int a52_flags;
sample_t a52_level, a52_bias;
int a52_sample_rate;
int a52_bit_rate;
#define AUDIO_FRAME_SIZE 65535
char *audio_buffer;
char *input_audio_buffer;
int input_audio_buffer_len;
extern sh_audio_t *sh_audio;
int audio_resample_flg = FALSE;
ReSampleContext *audio_resample_ctx;
int audio_header_decoded = FALSE;
audio_header_t audio_header;
DartStruct DART;
extern HMTX dart_cb_mtx;
void CalcAVtime(void);
int a52_fill_buffer(sh_audio_t *sh_audio)
{
int length;
input_audio_buffer_len = 0;
// Sync frame
for(;;)
{
while(input_audio_buffer_len < 7)
{
int chr;
chr = demux_getc(sh_audio->ds);
if (chr < 0)
return -1;
input_audio_buffer[input_audio_buffer_len++] = chr;
}
length = a52_syncinfo(input_audio_buffer,
&a52_flags,
&a52_sample_rate,
&a52_bit_rate);
// if done
if(length >= 7 && length <= 3840)
break;
// resync
memmove(input_audio_buffer, input_audio_buffer + 1, 6);
input_audio_buffer_len--;
}
// read a52 frame
input_audio_buffer_len = demux_read_data(sh_audio->ds,
input_audio_buffer + 7,
length - 7);
return length;
}
// MP3 decoder buffer callback:
int mp3_fill_buffer(char *buf, int size)
{
return demux_read_data(sh_audio->ds, buf, size);
}
void resync_audio_stream(sh_audio_t *sh_audio)
{
switch(sh_audio->codec->codec_type)
{
case AUDIO_MPEG:
MP3_DecodeFrame(NULL,-2); // resync
MP3_DecodeFrame(NULL,-2); // resync
MP3_DecodeFrame(NULL,-2); // resync
break;
case AUDIO_AC3:
// nope
break;
}
}
void skip_audio_frame(sh_audio_t *sh_audio)
{
switch(sh_audio->codec->codec_type)
{
case AUDIO_MPEG:
MP3_DecodeFrame(NULL,-2); // skip MPEG frame
break;
case AUDIO_AC3:
a52_fill_buffer(sh_audio); // skip AC3 frame
break;
}
}
size_t dartCallback (void *Buffer, size_t BufferSize)
{
int rc, hr, bsize, usize, len;
int isamp, osamp;
DWORD srcsize = 0;
unsigned char *tmp_buffer;
CalcAVtime();
DosRequestMutexSem(dart_cb_mtx, (ULONG)SEM_INDEFINITE_WAIT);
if (DART.Stopped == TRUE)
return 0;
audio_header.dart_buffer_size = BufferSize;
bsize = BufferSize;
usize = 0;
tmp_buffer = (unsigned char *)malloc(AUDIO_FRAME_SIZE);
if (audio_header.audio_buffer_used > 0)
{
memmove((BYTE *)Buffer + usize, audio_buffer, audio_header.audio_buffer_used);
bsize -= audio_header.audio_buffer_used;
usize += audio_header.audio_buffer_used;
audio_header.audio_buffer_used = 0;
}
while(bsize > 0)
{
len = audio_decode(sh_audio, FALSE);
if (len <= 0)
goto Exit;
if (audio_resample_flg > 0)
{
isamp = len/(audio_header.channels * 2);
if (isamp > 0)
{
osamp = audio_resample(audio_resample_ctx, (short *)tmp_buffer, (short *)audio_buffer, isamp);
osamp *= (audio_header.channels * 2);
}
else
osamp = 0;
}
else
{
memcpy(tmp_buffer, audio_buffer, len);
osamp = len;
}
if(osamp == 0)
goto Exit;
if (osamp <= bsize)
{
memcpy((BYTE *)Buffer + usize, tmp_buffer, osamp);
bsize -= osamp;
usize += osamp;
audio_header.audio_buffer_used = 0;
} else {
memcpy((BYTE *)Buffer + usize, tmp_buffer, bsize);
audio_header.audio_buffer_used = osamp - bsize;
memmove(audio_buffer, tmp_buffer + bsize, audio_header.audio_buffer_used);
bsize = 0;
}
}
Exit:
free(tmp_buffer);
DosReleaseMutexSem(dart_cb_mtx);
return BufferSize;
}
int audio_init(sh_audio_t *sh_audio, int AudioDeviceID, int Resample)
{
int rc;
audio_resample_flg = Resample;
audio_buffer = (UCHAR *)malloc(AUDIO_FRAME_SIZE * 4);
audio_header.audio_buffer_used = 0;
input_audio_buffer = (UCHAR *)malloc(AUDIO_FRAME_SIZE * 4);
input_audio_buffer_len = 0;
memset(&audio_header, 0, sizeof(audio_header_t));
switch(sh_audio->codec->codec_type)
{
case AUDIO_MPEG:
MP3_Init();
MP3_DecodeFrame(audio_buffer, -1);
audio_header.sample_rate = MP3_samplerate;
audio_header.bit_rate = MP3_bitrate;
// audio_header.channels = MP3_channels;
audio_header.channels = 2;
audio_header.format = MCI_WAVE_FORMAT_PCM;
audio_header.bits_per_sample = BPS_16;
sh_audio->i_bps = MP3_bitrate*(1000/8);
break;
case AUDIO_AC3:
{
a52_state = a52_init(0);
if (a52_state == NULL)
return FALSE;
if (a52_fill_buffer(sh_audio) < 0)
return FALSE;
a52_flags = A52_STEREO;
a52_flags |= A52_ADJUST_LEVEL;
a52_level = 1;
a52_bias = 384;
if (a52_frame(a52_state,
input_audio_buffer,
&a52_flags, &a52_level, a52_bias) != 0)
return FALSE;
audio_header.sample_rate = a52_sample_rate;
audio_header.bit_rate = a52_bit_rate / 1000;
audio_header.channels = 2;
audio_header.format = MCI_WAVE_FORMAT_PCM;
audio_header.bits_per_sample = BPS_16;
sh_audio->i_bps = a52_bit_rate*(1000/8);
}
break;
case AUDIO_PCM:
audio_header.sample_rate = sh_audio->wf->nSamplesPerSec;
audio_header.bit_rate = sh_audio->wf->nAvgBytesPerSec/1000;
audio_header.channels = sh_audio->wf->nChannels;
audio_header.format = MCI_WAVE_FORMAT_PCM;
sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
switch (sh_audio->wf->wBitsPerSample)
{
case 8:
audio_header.bits_per_sample = BPS_8;
break;
case 16:
audio_header.bits_per_sample = BPS_16;
break;
default:
audio_header.bits_per_sample = BPS_16;
break;
}
break;
default:
// mmmmmm...
break;
}
if (audio_resample_flg > 0)
{
switch(audio_resample_flg)
{
case RESAMPLE_TO_44100:
if (audio_header.sample_rate == 48000)
{
audio_header.resample_rate = 44100;
}
break;
case RESAMPLE_TO_48000:
if (audio_header.sample_rate != 48000)
{
audio_header.resample_rate = 48000;
}
break;
}
if (audio_header.resample_rate != 0)
{
audio_resample_ctx = audio_resample_init(audio_header.channels,
audio_header.channels,
audio_header.resample_rate,
audio_header.sample_rate);
printf("Audio: resample %d -> %d\n",
audio_header.sample_rate,
audio_header.resample_rate);
}
else
{
audio_resample_flg = RESAMPLE_NONE;
}
}
DART.Shareable = FALSE;
if (audio_header.resample_rate != 0)
{
rc = dart_init(AudioDeviceID,
audio_header.bits_per_sample,
audio_header.resample_rate,
audio_header.format,
audio_header.channels,
2,
dartCallback);
}
else
{
rc = dart_init(AudioDeviceID,
audio_header.bits_per_sample,
audio_header.sample_rate,
audio_header.format,
audio_header.channels,
2,
dartCallback);
}
sh_audio->o_bps = audio_header.channels * audio_header.sample_rate * 2;
return rc;
}
int audio_decode(sh_audio_t *sh_audio, int init_flag)
{
UCHAR *ac3_audio_data = NULL;
UCHAR compr_audio_data[2048];
int in_ptr = 0;
UCHAR *temp_data;
int len, size, total_len, i, ret;
int out_size = 0;
static int read_size = 1024;
Next:
switch(sh_audio->codec->codec_type)
{
case AUDIO_MPEG:
{
total_len = MP3_DecodeFrame(audio_buffer, -1);
if (total_len == 0)
total_len = -1;
}
break;
case AUDIO_AC3:
{
int rc;
if (input_audio_buffer_len == 0)
{
if (a52_fill_buffer(sh_audio) < 0)
{
total_len = -1;
break;
}
}
input_audio_buffer_len = 0;
a52_flags = A52_STEREO;
a52_flags |= A52_ADJUST_LEVEL;
a52_level = 1;
a52_bias = 384;
rc = a52_frame(a52_state,
input_audio_buffer,
&a52_flags,
&a52_level,
a52_bias);
if (rc != 0)
total_len = -1;
a52_dynrng(a52_state, NULL, NULL);
total_len = 0;
for (i = 0; i < 6; i++)
{
if (a52_block(a52_state) != 0)
break;
float2s16_2(a52_samples(a52_state), (int8_t *)audio_buffer + total_len);
total_len += (256 * 4);
}
}
break;
case AUDIO_PCM:
{
total_len = demux_read_data(sh_audio->ds, audio_buffer, 1024);
if (total_len == 0)
total_len = -1;
}
break;
}
return total_len;
}