mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-10-28 05:40:23 -04:00
166 lines
4.3 KiB
C
166 lines
4.3 KiB
C
/***************************************************************************/
|
|
/* This code has been fully inspired from various place */
|
|
/* I will give their name later. May they be bless .... It works */
|
|
/* */
|
|
/* For the moment test it. */
|
|
/* */
|
|
/* 27-08-00 -- Ze'ev Maor -- fixed recovery from flase syncword detection */
|
|
/* */
|
|
/* 24-08-00 -- Ze'ev Maor -- Modified for integrtion with DXR3-OMS-plugin */
|
|
/***************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <libac3/ac3.h>
|
|
#include <libac3/ac3_internal.h>
|
|
#include <libac3/parse.h>
|
|
#include <libac3/crc.h>
|
|
|
|
#include "output.h"
|
|
|
|
void swab(const void*, void*, size_t);
|
|
|
|
#define BLOCK_SIZE 6144
|
|
|
|
static unsigned char buf[BLOCK_SIZE];
|
|
static uint32_t sbuffer_size;
|
|
static syncinfo_t syncinfo;
|
|
static char *sbuffer;
|
|
static int done_banner;
|
|
|
|
static uint32_t
|
|
buffer_syncframe(syncinfo_t *syncinfo, uint8_t **start, uint8_t *end)
|
|
{
|
|
uint8_t *cur = *start;
|
|
uint16_t syncword = syncinfo->syncword;
|
|
uint32_t ret = 0;
|
|
|
|
//
|
|
// Find an ac3 sync frame.
|
|
//
|
|
while(syncword != 0x0b77)
|
|
{
|
|
if(cur >= end)
|
|
goto done;
|
|
syncword = (syncword << 8) + *cur++;
|
|
}
|
|
|
|
//need the next 3 bytes to decide how big the frame is
|
|
while(sbuffer_size < 3)
|
|
{
|
|
if(cur >= end)
|
|
goto done;
|
|
|
|
sbuffer[sbuffer_size++] = *cur++;
|
|
}
|
|
|
|
parse_syncinfo_data(syncinfo,sbuffer);
|
|
|
|
while(sbuffer_size < (uint32_t)syncinfo->frame_size * 2 - 2)
|
|
{
|
|
if(cur >= end)
|
|
goto done;
|
|
|
|
sbuffer[sbuffer_size++] = *cur++;
|
|
}
|
|
|
|
crc_init();
|
|
crc_process_frame(sbuffer,syncinfo->frame_size * 2 - 2);
|
|
|
|
if(!crc_validate())
|
|
{
|
|
//error_flag = 1;
|
|
fprintf(stderr,"** CRC failed - skipping frame **\n");
|
|
syncword = 0xffff;
|
|
sbuffer_size = 0;
|
|
bzero(buf,BLOCK_SIZE);
|
|
|
|
goto done;
|
|
}
|
|
//
|
|
//if we got to this point, we found a valid ac3 frame to decode
|
|
//
|
|
|
|
//reset the syncword for next time
|
|
syncword = 0xffff;
|
|
sbuffer_size = 0;
|
|
ret = 1;
|
|
|
|
done:
|
|
syncinfo->syncword = syncword;
|
|
*start = cur;
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
init_spdif(void)
|
|
{
|
|
sbuffer_size = 0;
|
|
sbuffer = &buf[10];
|
|
done_banner = 0;
|
|
}
|
|
|
|
int
|
|
output_spdif_zero(int frames)
|
|
{
|
|
int res;
|
|
|
|
buf[0] = 0x72; buf[1] = 0xf8; // spdif syncword
|
|
buf[2] = 0x1f; buf[3] = 0x4e; // ..............
|
|
buf[4] = 0x00; // null frame (no data)
|
|
buf[5] = 7 << 5; // stream = 7
|
|
buf[6] = 0x00; buf[7] = 0x00; // frame size
|
|
memset(&buf[8], 0, BLOCK_SIZE - 8);
|
|
while (frames-- > 0) {
|
|
res = output_play((short *)buf, BLOCK_SIZE / 2 / 2); /* 2 channels, 16-bit samples */
|
|
if (res < 0)
|
|
return res;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
output_spdif_leadin(void)
|
|
{
|
|
memset(buf, 0, 8);
|
|
return output_play((short *)buf, 8);
|
|
}
|
|
|
|
int
|
|
output_spdif(uint8_t *data_start, uint8_t *data_end, int quiet)
|
|
{
|
|
int ret = 0, res;
|
|
|
|
while(buffer_syncframe(&syncinfo, &data_start, data_end))
|
|
{
|
|
buf[0] = 0x72; buf[1] = 0xf8; // spdif syncword
|
|
buf[2] = 0x1f; buf[3] = 0x4e; // ..............
|
|
buf[4] = 0x01; // AC3 data
|
|
buf[5] = buf[13] & 7; // bsmod, stream = 0
|
|
buf[6] = (syncinfo.frame_size * 16) & 0xff;
|
|
buf[7] = ((syncinfo.frame_size * 16) >> 8) & 0xff;
|
|
buf[8] = 0x77; buf[9] = 0x0b; // AC3 syncwork
|
|
|
|
if (!done_banner && !quiet) {
|
|
fprintf(stdout,"AC3 Stream ");
|
|
fprintf(stdout,"%2.1f KHz",syncinfo.sampling_rate * 1e-3);
|
|
fprintf(stdout,"%4d kbps",syncinfo.bit_rate);
|
|
fprintf(stdout,"\n");
|
|
done_banner = 1;
|
|
}
|
|
|
|
#ifndef _a_b_c_d_e_f /* WORDS_BIGENDIAN */
|
|
// extract_ac3 seems to write swabbed data
|
|
swab(&buf[10], &buf[10], syncinfo.frame_size * 2 - 2);
|
|
#endif
|
|
res = output_play((short *)buf, BLOCK_SIZE / 2 / 2); /* 2 channels, 16-bit samples */
|
|
ret = ret < 0 ? ret : res;
|
|
bzero(buf,BLOCK_SIZE);
|
|
}
|
|
return ret;
|
|
}
|