File:  [DVB] / libsoftmpeg / src / mpegaudio.c
Revision 1.1: download - view: text, annotated - select for diffs
Fri Feb 6 10:56:16 2004 UTC (20 years, 4 months ago) by hunold
Branches: MAIN
CVS tags: HEAD
Initial release. It's done.

/** taken from ffmpeg-0.4.8:
 * @file mpegaudio.h
 * mpeg audio declarations for both encoder and decoder.
 */

/* ffmpeg and the associated libraries [...] are licensed under the
   Lesser GNU General Public License. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "audio.h"

static const uint16_t mpa_bitrate_tab[2][3][15] = {
	{{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},
	 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384},
	 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}},
	{{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
	 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
	 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
	 }
};

static const uint16_t mpa_freq_tab[3] = { 44100, 48000, 32000 };

/* fast header check for resync */
static int check_header(uint32_t header)
{
	/* header */
	if ((header & 0xffe00000) != 0xffe00000)
		return -1;
	/* layer check */
	if (((header >> 17) & 3) == 0)
		return -1;
	/* bit rate */
	if (((header >> 12) & 0xf) == 0xf)
		return -1;
	/* frequency */
	if (((header >> 10) & 3) == 3)
		return -1;
	return 0;
}

/* header + layer + bitrate + freq + lsf/mpeg25 */
#define SAME_HEADER_MASK \
   (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19))

#define MPA_STEREO  0
#define MPA_JSTEREO 1
#define MPA_DUAL    2
#define MPA_MONO    3

int decode_header(struct audio_config *s, uint32_t header)
{
	int sample_rate, frame_size, mpeg25, padding;
	int sample_rate_index, bitrate_index;

	if (0 != check_header(header)) {
		return -1;
	}

	if (header & (1 << 20)) {
		s->lsf = (header & (1 << 19)) ? 0 : 1;
		mpeg25 = 0;
	} else {
		s->lsf = 1;
		mpeg25 = 1;
	}

	s->layer = 4 - ((header >> 17) & 3);
	/* extract frequency */
	sample_rate_index = (header >> 10) & 3;
	sample_rate = mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25);
	sample_rate_index += 3 * (s->lsf + mpeg25);
	s->sample_rate_index = sample_rate_index;
	s->error_protection = ((header >> 16) & 1) ^ 1;
	s->sample_rate = sample_rate;

	bitrate_index = (header >> 12) & 0xf;
	padding = (header >> 9) & 1;
	//extension = (header >> 8) & 1;
	s->mode = (header >> 6) & 3;
	s->mode_ext = (header >> 4) & 3;
	//copyright = (header >> 3) & 1;
	//original = (header >> 2) & 1;
	//emphasis = header & 3;

	if (s->mode == MPA_MONO)
		s->nb_channels = 1;
	else
		s->nb_channels = 2;

	if (bitrate_index != 0) {
		frame_size = mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index];
		s->bit_rate = frame_size * 1000;
		switch (s->layer) {
		case 1:
			frame_size = (frame_size * 12000) / sample_rate;
			frame_size = (frame_size + padding) * 4;
			break;
		case 2:
			frame_size = (frame_size * 144000) / sample_rate;
			frame_size += padding;
			break;
		default:
		case 3:
			frame_size = (frame_size * 144000) / (sample_rate << s->lsf);
			frame_size += padding;
			break;
		}
		s->frame_size = frame_size;
	} else {
		/* if no frame size computed, signal it */
		if (!s->free_format_frame_size)
			return 1;
		/* free format: compute bitrate and real frame size from the
		   frame size we extracted by reading the bitstream */
		s->frame_size = s->free_format_frame_size;
		switch (s->layer) {
		case 1:
			s->frame_size += padding * 4;
			s->bit_rate = (s->frame_size * sample_rate) / 48000;
			break;
		case 2:
			s->frame_size += padding;
			s->bit_rate = (s->frame_size * sample_rate) / 144000;
			break;
		default:
		case 3:
			s->frame_size += padding;
			s->bit_rate = (s->frame_size * (sample_rate << s->lsf)) / 144000;
			break;
		}
	}

#if defined(DEBUG)
	printf("layer%d, %d Hz, %d kbits/s, ", s->layer, s->sample_rate, s->bit_rate);
	if (s->nb_channels == 2) {
		if (s->layer == 3) {
			if (s->mode_ext & MODE_EXT_MS_STEREO)
				printf("ms-");
			if (s->mode_ext & MODE_EXT_I_STEREO)
				printf("i-");
		}
		printf("stereo");
	} else {
		printf("mono");
	}
	printf("\n");
#endif
	return 0;
}

LinuxTV legacy CVS <linuxtv.org/cvs>