📄 dec_mac.cpp
字号:
/* -*- linux-c -*- Copyright (C) 2005 Tom Szilagyi This program 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. This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. $Id: dec_mac.cpp,v 1.4 2006/09/09 19:03:58 tszilagyi Exp $*/#include <config.h>#include <stdio.h>#include <stdlib.h>#ifdef HAVE_MAC/* expand this to nothing so there's no error when including MACLib.h *//* -- talkin' about cross-platform libraries? */#define DLLEXPORT/* more cross-platform compatibility... */#include <mac/NoWindows.h>#include <mac/All.h>#include <mac/MACLib.h>#include <mac/CharacterHelper.h>#endif /* HAVE_MAC */#include "dec_mac.h"extern size_t sample_size;#define SAMPLES_PER_READ 2048#ifdef HAVE_MAC/* return 1 if reached end of stream, 0 else */intdecode_mac(decoder_t * dec) { mac_pdata_t * pd = (mac_pdata_t *)dec->pdata; file_decoder_t * fdec = dec->fdec; IAPEDecompress * pdecompress = (IAPEDecompress *)pd->decompress; int blocks_to_read = SAMPLES_PER_READ; int bytes = blocks_to_read * pd->block_align; int act_read, act_bytes; unsigned long scale = 1 << (pd->bits_per_sample - 1); float fbuf[2 * SAMPLES_PER_READ]; int n = 0; act_read = blocks_to_read; act_bytes = bytes; switch (pd->bits_per_sample) { case 8: char data8[2 * SAMPLES_PER_READ]; pdecompress->GetData(data8, blocks_to_read, &act_read); if (!act_read) { return 1; } for (int i = 0; i < act_read; i++) { for (unsigned int j = 0; j < pd->channels; j++) { fbuf[n] = (float)(data8[n] * fdec->voladj_lin / scale); ++n; } } break; case 16: short data16[2 * SAMPLES_PER_READ]; pdecompress->GetData((char *)data16, blocks_to_read, &act_read); if (!act_read) { return 1; } for (int i = 0; i < act_read; i++) { for (unsigned int j = 0; j < pd->channels; j++) { fbuf[n] = (float)(data16[n] * fdec->voladj_lin / scale); ++n; } } break; case 32: int data32[2 * SAMPLES_PER_READ]; pdecompress->GetData((char *)data32, blocks_to_read, &act_read); if (!act_read) { return 1; } for (int i = 0; i < act_read; i++) { for (unsigned int j = 0; j < pd->channels; j++) { fbuf[n] = (float)(data32[n] * fdec->voladj_lin / scale); ++n; } } break; default: printf("programmer error, please report: invalid bits_per_sample = %d " "in decode_mac()\n", pd->bits_per_sample); break; } rb_write(pd->rb, (char *)fbuf, act_read * pd->channels * sample_size); return 0;}decoder_t *mac_decoder_init(file_decoder_t * fdec) { decoder_t * dec = NULL; if ((dec = (decoder_t *)calloc(1, sizeof(decoder_t))) == NULL) { fprintf(stderr, "dec_mac.c: mac_decoder_new() failed: calloc error\n"); return NULL; } dec->fdec = fdec; if ((dec->pdata = calloc(1, sizeof(mac_pdata_t))) == NULL) { fprintf(stderr, "dec_mac.c: mac_decoder_new() failed: calloc error\n"); return NULL; } dec->init = mac_decoder_init; dec->destroy = mac_decoder_destroy; dec->open = mac_decoder_open; dec->close = mac_decoder_close; dec->read = mac_decoder_read; dec->seek = mac_decoder_seek; return dec;}voidmac_decoder_destroy(decoder_t * dec) { free(dec->pdata); free(dec);}intmac_decoder_open(decoder_t * dec, char * filename) { mac_pdata_t * pd = (mac_pdata_t *)dec->pdata; file_decoder_t * fdec = dec->fdec; IAPEDecompress * pdecompress = (IAPEDecompress *)pd->decompress; int ret = 0; wchar_t * pUTF16 = GetUTF16FromANSI(filename); pdecompress = CreateIAPEDecompress(pUTF16, &ret); free(pUTF16); if (!pdecompress || ret != ERROR_SUCCESS) { return DECODER_OPEN_BADLIB; } pd->decompress = (void *)pdecompress; pd->sample_rate = pdecompress->GetInfo(APE_INFO_SAMPLE_RATE); pd->bits_per_sample = pdecompress->GetInfo(APE_INFO_BITS_PER_SAMPLE); pd->bitrate = pdecompress->GetInfo(APE_DECOMPRESS_AVERAGE_BITRATE); pd->channels = pdecompress->GetInfo(APE_INFO_CHANNELS); pd->length_in_ms = pdecompress->GetInfo(APE_DECOMPRESS_LENGTH_MS); pd->block_align = pdecompress->GetInfo(APE_INFO_BLOCK_ALIGN); pd->compression_level = pdecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL); if ((pd->channels != 1) && (pd->channels != 2)) { printf("Sorry, MAC file with %d channels is not supported.\n", pd->channels); return DECODER_OPEN_BADLIB; } if ((pd->bits_per_sample != 8) && (pd->bits_per_sample != 16) && (pd->bits_per_sample != 32)) { printf("Sorry, MAC file with %d bits per sample is not supported.\n", pd->bits_per_sample); return DECODER_OPEN_BADLIB; } pd->is_eos = 0; pd->rb = rb_create(pd->channels * sample_size * RB_MAC_SIZE); fdec->channels = pd->channels; fdec->SR = pd->sample_rate; fdec->file_lib = MAC_LIB; switch (pd->compression_level) { case COMPRESSION_LEVEL_FAST: fdec->fileinfo.format_minor = MAC_COMP_FAST; break; case COMPRESSION_LEVEL_NORMAL: fdec->fileinfo.format_minor = MAC_COMP_NORMAL; break; case COMPRESSION_LEVEL_HIGH: fdec->fileinfo.format_minor = MAC_COMP_HIGH; break; case COMPRESSION_LEVEL_EXTRA_HIGH: fdec->fileinfo.format_minor = MAC_COMP_EXTRA; break; case COMPRESSION_LEVEL_INSANE: fdec->fileinfo.format_minor = MAC_COMP_INSANE; break; default: printf("Unknown MAC compression level %d\n", pd->compression_level); fdec->fileinfo.format_minor = 0; break; } fdec->fileinfo.total_samples = (unsigned long long)(pd->sample_rate / 1000.0f * pd->length_in_ms); fdec->fileinfo.format_major = FORMAT_MAC; fdec->fileinfo.bps = pd->bitrate * 1000; return DECODER_OPEN_SUCCESS;}voidmac_decoder_close(decoder_t * dec) { mac_pdata_t * pd = (mac_pdata_t *)dec->pdata; IAPEDecompress * pdecompress = (IAPEDecompress *)pd->decompress; delete(pdecompress); rb_free(pd->rb);}unsigned intmac_decoder_read(decoder_t * dec, float * dest, int num) { mac_pdata_t * pd = (mac_pdata_t *)dec->pdata; unsigned int numread = 0; int n_avail = 0; while ((rb_read_space(pd->rb) < num * pd->channels * sample_size) && (!pd->is_eos)) { pd->is_eos = decode_mac(dec); } n_avail = rb_read_space(pd->rb) / (pd->channels * sample_size); if (n_avail > num) n_avail = num; rb_read(pd->rb, (char *)dest, n_avail * pd->channels * sample_size); numread = n_avail; return numread;}voidmac_decoder_seek(decoder_t * dec, unsigned long long seek_to_pos) { mac_pdata_t * pd = (mac_pdata_t *)dec->pdata; file_decoder_t * fdec = dec->fdec; IAPEDecompress * pdecompress = (IAPEDecompress *)pd->decompress; char flush_dest; pdecompress->Seek(seek_to_pos); fdec->samples_left = fdec->fileinfo.total_samples - seek_to_pos; /* empty mac decoder ringbuffer */ while (rb_read_space(pd->rb)) rb_read(pd->rb, &flush_dest, sizeof(char));}#elsedecoder_t *mac_decoder_init(file_decoder_t * fdec) { return NULL;}#endif /* HAVE_MAC */// vim: shiftwidth=8:tabstop=8:softtabstop=8 :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -