Fixed up CVS, added missing files.

This commit is contained in:
vspader 2005-06-07 04:16:15 +00:00
parent 38706770cc
commit 180dcd01f2
93 changed files with 30293 additions and 0 deletions

View file

@ -0,0 +1,366 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <stdlib.h>
#include <string.h>
//#include "filestream.h"
#include "aacinfo.h"
#define ADIF_MAX_SIZE 30 /* Should be enough */
#define ADTS_MAX_SIZE 10 /* Should be enough */
static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
static int read_ADIF_header(FILE *file, faadAACInfo *info)
{
int bitstream;
unsigned char buffer[ADIF_MAX_SIZE];
int skip_size = 0;
int sf_idx;
/* Get ADIF header data */
info->headertype = 1;
if(fread(buffer, 1, ADIF_MAX_SIZE, file) < 0)
return -1;
/* copyright string */
if(buffer[0] & 0x80)
skip_size += 9; /* skip 9 bytes */
bitstream = buffer[0 + skip_size] & 0x10;
info->bitrate = ((unsigned int)(buffer[0 + skip_size] & 0x0F)<<19)|
((unsigned int)buffer[1 + skip_size]<<11)|
((unsigned int)buffer[2 + skip_size]<<3)|
((unsigned int)buffer[3 + skip_size] & 0xE0);
if (bitstream == 0)
{
info->object_type = ((buffer[6 + skip_size]&0x01)<<1)|((buffer[7 + skip_size]&0x80)>>7);
sf_idx = (buffer[7 + skip_size]&0x78)>>3;
} else {
info->object_type = (buffer[4 + skip_size] & 0x18)>>3;
sf_idx = ((buffer[4 + skip_size] & 0x07)<<1)|((buffer[5 + skip_size] & 0x80)>>7);
}
info->sampling_rate = sample_rates[sf_idx];
return 0;
}
static int read_ADTS_header(FILE *file, faadAACInfo *info,
unsigned long **seek_table, int *seek_table_len,
int tagsize, int no_seek_table)
{
/* Get ADTS header data */
unsigned char buffer[ADTS_MAX_SIZE];
int frames, framesinsec=0, t_framelength = 0, frame_length, sr_idx, ID;
int second = 0, pos;
int i;
float frames_per_sec = 0;
unsigned long bytes;
unsigned long *tmp_seek_table = NULL;
info->headertype = 2;
/* Read all frames to ensure correct time and bitrate */
for(frames=0; /* */; frames++, framesinsec++)
{
/* If streaming, only go until we hit 5 seconds worth */
/* if(file->http)
{
if(frames >= 43 * 5)
{
break;
}
}
*/
pos = ftell(file);//tell_filestream(file);
/* 12 bit SYNCWORD */
bytes = fread(buffer, 1, ADTS_MAX_SIZE, file);
if(bytes != ADTS_MAX_SIZE)
{
/* Bail out if no syncword found */
break;
}
/* check syncword */
if (!((buffer[0] == 0xFF)&&((buffer[1] & 0xF6) == 0xF0)))
break;
if(!frames)
{
/* fixed ADTS header is the same for every frame, so we read it only once */
/* Syncword found, proceed to read in the fixed ADTS header */
ID = buffer[1] & 0x08;
info->object_type = (buffer[2]&0xC0)>>6;
sr_idx = (buffer[2]&0x3C)>>2;
info->channels = ((buffer[2]&0x01)<<2)|((buffer[3]&0xC0)>>6);
frames_per_sec = sample_rates[sr_idx] / 1024.f;
}
/* ...and the variable ADTS header */
if (ID == 0) {
info->version = 4;
} else { /* MPEG-2 */
info->version = 2;
}
frame_length = ((((unsigned int)buffer[3] & 0x3)) << 11)
| (((unsigned int)buffer[4]) << 3) | (buffer[5] >> 5);
t_framelength += frame_length;
// if(!file->http)
{
if(framesinsec == 43)
framesinsec = 0;
if(framesinsec == 0 && seek_table_len)
{
tmp_seek_table = (unsigned long *) realloc(tmp_seek_table, (second + 1) * sizeof(unsigned long));
tmp_seek_table[second] = pos;
}
if(framesinsec == 0)
second++;
}
/* NOTE: While simply skipping ahead by reading may seem to be more work than seeking,
it is actually much faster, and keeps compatibility with streaming */
//F THAT
fseek(file, frame_length - ADTS_MAX_SIZE, SEEK_CUR);
/* for(i=0; i < frame_length - ADTS_MAX_SIZE; i++)
{
if(read_byte_filestream(file) < 0)
break;
}
*/
}
if(seek_table_len)
{
*seek_table_len = second;
*seek_table = tmp_seek_table;
}
info->sampling_rate = sample_rates[sr_idx];
info->bitrate = (int)(((t_framelength / frames) * (info->sampling_rate/1024.0)) +0.5)*8;
/* if(file->http)
{
// Since we only use 5 seconds of aac data to get a rough bitrate, we must use a different
// method of calculating the overall length
if(filelength_filestream(file))
{
info->length = (int)((filelength_filestream(file)/(((info->bitrate*8)/1024)*16))*1000);
}
else
{
// Since the server didnt tell us how long the file is,
// we have no way of determining length
info->length = 0;
}
}
else
*/ {
info->length = (int)((float)(frames/frames_per_sec))*1000;
}
return 0;
}
int get_AAC_format(FILE *file, faadAACInfo *info,
unsigned long **seek_table, int *seek_table_len,
int no_seek_table)
{
unsigned long tagsize;
char buffer[10];
unsigned long file_len;
unsigned char adxx_id[5];
unsigned long tmp;
memset(info, 0, sizeof(faadAACInfo));
fseek(file, 0, SEEK_END);
file_len = ftell(file);
/* Skip the tag, if it's there */
tmp = fread(buffer, 1, 10, file);
if (StringComp(buffer, "ID3", 3) == 0)
{
unsigned int i;
/* high bit is not used */
tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
(buffer[8] << 7) | (buffer[9] << 0);
fseek(file, tagsize, SEEK_CUR);
tagsize += 10;
}
else
{
tagsize = 0;
fseek(file, 0, SEEK_SET);
}
if(file_len)
file_len -= tagsize;
tmp = fread(adxx_id, 1, 2, file);
//seek_filestream(file, tagsize, FILE_BEGIN);
adxx_id[5-1] = 0;
info->length = 0;
/* Determine the header type of the file, check the first two bytes */
if(strncasecmp((char *)adxx_id, "AD", 2) == 0)
{
/* We think its an ADIF header, but check the rest just to make sure */
tmp = fread(adxx_id+2, 1, 2, file);
if(strncasecmp((char *)adxx_id, "ADIF", 4) == 0)
{
read_ADIF_header(file, info);
}
}
else
{
/* No ADIF, check for ADTS header */
if ((adxx_id[0] == 0xFF)&&((adxx_id[1] & 0xF6) == 0xF0))
{
/* ADTS header located */
/* Since this routine must work for streams, we can't use the seek function to go backwards, thus
we have to use a quick hack as seen below to go back where we need to. */
fseek(file, -2, SEEK_CUR);
/* if(file->buffer_offset >= 2)
{
// simple seeking hack, though not really safe, the probability of it causing a problem is low.
file->buffer_offset -= 2;
file->file_offset -= 2;
}
*/
read_ADTS_header(file, info, seek_table, seek_table_len, tagsize,
no_seek_table);
}
else
{
/* Unknown/headerless AAC file, assume format: */
info->version = 2;
info->bitrate = 128000;
info->sampling_rate = 44100;
info->channels = 2;
info->headertype = 0;
info->object_type = 1;
}
}
return 0;
}
int StringComp(char const *str1, char const *str2, unsigned long len)
{
signed int c1 = 0, c2 = 0;
while (len--) {
c1 = *str1++;
c2 = *str2++;
if (c1 == 0 || c1 != c2)
break;
}
return c1 - c2;
}
#ifdef TEST
/* Program to test aacinfo functionality */
#include <stdio.h>
void main(int argc, char *argv[])
{
faadAACInfo info;
unsigned long *seek_table = NULL;
int seek_table_len = 0;
char *header, *object;
if (argc < 2)
{
fprintf(stderr, "USAGE: aacinfo aacfile.aac\n");
return;
}
get_AAC_format(argv[1], &info, &seek_table, &seek_table_len, 0);
fprintf(stdout, "MPEG version: %d\n", info.version);
fprintf(stdout, "channels: %d\n", info.channels);
fprintf(stdout, "sampling_rate: %d\n", info.sampling_rate);
fprintf(stdout, "bitrate: %d\n", info.bitrate);
fprintf(stdout, "length: %.3f\n", (float)info.length/1000.0);
switch (info.object_type)
{
case 0:
object = "MAIN";
break;
case 1:
object = "LC";
break;
case 2:
object = "SSR";
break;
case 3:
object = "LTP";
break;
}
fprintf(stdout, "object_type: %s\n", object);
switch (info.headertype)
{
case 0:
header = "RAW";
break;
case 1:
header = "ADIF";
break;
case 2:
header = "ADTS";
break;
}
fprintf(stdout, "headertype: %s\n", header);
}
#endif

View file

@ -0,0 +1,54 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifndef AACINFO_H__
#define AACINFO_H__
//#include "filestream.h"
#include <stdio.h>
typedef struct {
int version;
int channels;
int sampling_rate;
int bitrate;
int length;
int object_type;
int headertype;
} faadAACInfo;
int get_AAC_format(FILE *file, faadAACInfo *info,
unsigned long **seek_table, int *seek_table_len,
int no_seek_table);
static int read_ADIF_header(FILE *file, faadAACInfo *info);
static int read_ADTS_header(FILE *file, faadAACInfo *info,
unsigned long **seek_table, int *seek_table_len,
int tagsize, int no_seek_table);
int StringComp(char const *str1, char const *str2, unsigned long len);
#endif

View file

@ -0,0 +1,470 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
/* Not very portable yet */
#include <winsock2.h> // Note: Must be *before* windows.h
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "filestream.h"
#include "aacinfo.h"
/* TEMPROARY HACK */
#define CommonExit(A) MessageBox(NULL, A, "FAAD Plugin", MB_OK)
int winsock_init=0; // 0=winsock not initialized, 1=success
long m_local_buffer_size = 64;
long m_stream_buffer_size = 128;
FILE_STREAM *open_filestream(char *filename)
{
FILE_STREAM *fs;
if(StringComp(filename,"http://", 7) == 0)
{
fs = (FILE_STREAM *)LocalAlloc(LPTR, sizeof(FILE_STREAM) + m_stream_buffer_size * 1024);
if(fs == NULL)
return NULL;
fs->data = (unsigned char *)&fs[1];
if(http_file_open(filename, fs) < 0)
{
LocalFree(fs);
return NULL;
}
fs->http = 1;
}
else
{
fs = (FILE_STREAM*)LocalAlloc(LPTR, sizeof(FILE_STREAM) + m_local_buffer_size * 1024);
if(fs == NULL)
return NULL;
fs->data = (unsigned char *)&fs[1];
fs->stream = CreateFile(filename, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (fs->stream == INVALID_HANDLE_VALUE)
{
LocalFree(fs);
return NULL;
}
fs->http = 0;
}
fs->buffer_length = 0;
fs->buffer_offset = 0;
fs->file_offset = 0;
return fs;
}
int read_byte_filestream(FILE_STREAM *fs)
{
if(fs->buffer_offset == fs->buffer_length)
{
fs->buffer_offset = 0;
if(fs->http)
fs->buffer_length = recv(fs->inetStream, fs->data, m_stream_buffer_size * 1024, 0);
else
ReadFile(fs->stream, fs->data, m_local_buffer_size * 1024, &fs->buffer_length, 0);
if(fs->buffer_length <= 0)
{
if(fs->http)
{
int x;
x = WSAGetLastError();
if(x == 0)
{
/* Equivalent of a successful EOF for HTTP */
}
}
fs->buffer_length = 0;
return -1;
}
}
fs->file_offset++;
return fs->data[fs->buffer_offset++];
}
int read_buffer_filestream(FILE_STREAM *fs, void *data, int length)
{
int i, tmp;
unsigned char *data2 = (unsigned char *)data;
for(i=0; i < length; i++)
{
if((tmp = read_byte_filestream(fs)) < 0)
{
if(i)
{
break;
}
else
{
return -1;
}
}
data2[i] = tmp;
}
return i;
}
unsigned long filelength_filestream(FILE_STREAM *fs)
{
unsigned long fsize;
if (fs->http)
{
fsize = fs->http_file_length;
}
else
{
fsize = GetFileSize(fs->stream, NULL);
}
return fsize;
}
void seek_filestream(FILE_STREAM *fs, unsigned long offset, int mode)
{
if(fs->http)
{
return;
}
SetFilePointer(fs->stream, offset, NULL, mode);
if(mode == FILE_CURRENT)
fs->file_offset += offset;
else if(mode == FILE_END)
fs->file_offset = filelength_filestream(fs) + offset;
else
fs->file_offset = offset;
fs->buffer_length = 0;
fs->buffer_offset = 0;
}
unsigned long tell_filestream(FILE_STREAM *fs)
{
return fs->file_offset;
}
void close_filestream(FILE_STREAM *fs)
{
if(fs)
{
if (fs->http)
{
if (fs->inetStream)
{
/* The 'proper' way to close a TCP connection */
if(fs->inetStream)
{
CloseTCP(fs->inetStream);
}
}
}
else
{
if(fs->stream)
CloseHandle(fs->stream);
}
LocalFree(fs);
fs = NULL;
}
}
int WinsockInit()
{
/* Before using winsock, you must load the DLL... */
WSADATA wsaData;
/* Load version 2.0 */
if (WSAStartup( MAKEWORD( 2, 0 ), &wsaData ))
{
/* Disable streaming */
return -1;
}
winsock_init = 1;
return 0;
}
void WinsockDeInit()
{
/* Unload the DLL */
if(winsock_init)
WSACleanup();
}
int FindCRLF(char *str)
{
int i;
for(i=0; i != lstrlen(str) && str[i] != '\r'; i++);
return i;
}
void CloseTCP(int s)
{
char tempbuf[1024];
/* Set the socket to ignore any new incoming data */
shutdown(s, 1);
/* Get any old remaining data */
while(recv(s, tempbuf, 1024, 0) > 0);
/* Deallocate the socket */
closesocket(s);
}
int resolve_host(char *host, SOCKADDR_IN *sck_addr, unsigned short remote_port)
{
HOSTENT *hp;
if (isalpha(host[0]))
{
/* server address is a name */
hp = gethostbyname(host);
}
else
{
unsigned long addr;
/* Convert nnn.nnn address to a usable one */
addr = inet_addr(host);
hp = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (hp == NULL)
{
char tmp[128];
wsprintf(tmp, "Error resolving host address [%s]!\n", host);
CommonExit(tmp);
return -1;
}
ZeroMemory(sck_addr, sizeof(SOCKADDR_IN));
sck_addr->sin_family = AF_INET;
sck_addr->sin_port = htons(remote_port);
CopyMemory(&sck_addr->sin_addr, hp->h_addr, hp->h_length);
return 0;
}
int http_file_open(char *url, FILE_STREAM *fs)
{
SOCKET sck;
SOCKADDR_IN host;
char server[1024], file[1024], request[1024], *temp = NULL, *tmpfile = NULL;
int i, j, port = 80, bytes_recv, http_code;
/* No winsock, no streaming */
if(!winsock_init)
{
return -1;
}
url += 7; // Skip over http://
/* Extract data from the URL */
for(i=0; url[i] != '/' && url[i] != ':' && url[i] != 0; i++);
ZeroMemory(server, 1024);
CopyMemory(server, url, i);
if(url[i] == ':')
{
/* A certain port was specified */
port = atol(url + (i + 1));
}
for(; url[i] != '/' && url[i] != 0; i++);
ZeroMemory(file, 1024);
CopyMemory(file, url + i, lstrlen(url));
/* END OF URL PARSING */
/* Create a TCP/IP socket */
sck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sck == INVALID_SOCKET)
{
CommonExit("Error creating TCP/IP new socket");
return -1;
}
/* Resolve the host address (turn www.blah.com into an IP) */
if(resolve_host(server, &host, (unsigned short)port))
{
CommonExit("Error resolving host address");
CloseTCP(sck);
return -1;
}
/* Connect to the server */
if(connect(sck, (SOCKADDR *)&host, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
CommonExit("Error connecting to remote server");
CloseTCP(sck);
return -1;
}
tmpfile = calloc(1, (strlen(file) * 3) + 1);
/* Encode URL */
for(i=0, j=0; i < (int)strlen(file); i++)
{
if((unsigned char)file[i] <= 31 || (unsigned char)file[i] >= 127)
{
/* encode ASCII-control characters */
wsprintf(tmpfile + j, "%%%X", (unsigned char)file[i]);
j += 3;
continue;
}
else
{
switch(file[i])
{
/* encode characters that could confuse some servers */
case ' ':
case '"':
case '>':
case '<':
case '#':
case '%':
case '{':
case '}':
case '|':
case '\\':
case '^':
case '~':
case '[':
case ']':
case '`':
wsprintf(tmpfile + j, "%%%X", (unsigned char)file[i]);
j += 3;
continue;
}
}
tmpfile[j] = file[i];
j++;
}
wsprintf(request, "GET %s\r\n\r\n", tmpfile);
free(tmpfile);
/* Send the request */
if(send(sck, request, lstrlen(request), 0) <= 0)
{
/* Error sending data */
CloseTCP(sck);
return -1;
}
ZeroMemory(request, 1024);
/* Send the request */
if((bytes_recv = recv(sck, request, 1024, 0)) <= 0)
{
/* Error sending data */
CloseTCP(sck);
return -1;
}
if(StringComp(request,"HTTP/1.", 7) != 0)
{
/* Invalid header */
CloseTCP(sck);
return -1;
}
http_code = atol(request + 9);
if(http_code < 200 || http_code > 299)
{
/* HTTP error */
CloseTCP(sck);
return -1;
}
// Search for a length field
fs->http_file_length = 0;
/* Limit search to only 20 loops */
if((temp = strstr(request, "Content-Length: ")) != NULL)
{
/* Has a content-length field, copy into structure */
fs->http_file_length = atol(temp + 16);
}
/* Copy the handle data into the structure */
fs->inetStream = sck;
/* Copy any excess data beyond the header into the filestream buffers */
temp = strstr(request, "\r\n\r\n");
if(temp)
{
temp += 4;
}
if(temp - request < bytes_recv)
{
memcpy(fs->data, temp, (temp - request) - bytes_recv);
fs->buffer_length = (temp - request) - bytes_recv;
fs->buffer_offset = 0;
}
return 0;
}

View file

@ -0,0 +1,57 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifndef FILESTREAM_H
#define FILESTREAM_H
typedef struct {
HANDLE stream;
unsigned short inetStream;
unsigned char *data;
int http;
int buffer_offset;
int buffer_length;
int file_offset;
int http_file_length;
} FILE_STREAM;
extern long m_local_buffer_size;
extern long m_stream_buffer_size;
FILE_STREAM *open_filestream(char *filename);
int read_byte_filestream(FILE_STREAM *fs);
int read_buffer_filestream(FILE_STREAM *fs, void *data, int length);
unsigned long filelength_filestream(FILE_STREAM *fs);
void close_filestream(FILE_STREAM *fs);
void seek_filestream(FILE_STREAM *fs, unsigned long offset, int mode);
unsigned long tell_filestream(FILE_STREAM *fs);
int http_file_open(char *url, FILE_STREAM *fs);
int WinsockInit();
void WinsockDeInit();
void CloseTCP(int s);
#endif

View file

@ -0,0 +1,755 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
Free Software Foundation, Inc.
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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef __STDC__
# ifndef const
# define const
# endif
#endif
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || !__MacOSX__
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#endif /* GNU C library. */
/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
long-named option. Because this is not POSIX.2 compliant, it is
being phased out. */
/* #define GETOPT_COMPAT */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
#define BAD_OPTION '\0'
int optopt = BAD_OPTION;
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#define my_strlen strlen
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
#if __STDC__ || defined(PROTO)
extern char *getenv(const char *name);
extern int strcmp (const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, unsigned int n);
static int my_strlen(const char *s);
static char *my_index (const char *str, int chr);
#else
extern char *getenv ();
#endif
static int
my_strlen (str)
const char *str;
{
int n = 0;
while (*str++)
n++;
return n;
}
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
#endif /* GNU C library. */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved.
To perform the swap, we first reverse the order of all elements. So
all options now come before all non options, but they are in the
wrong order. So we put back the options and non options in original
order by reversing them again. For example:
original input: a b c -x -y
reverse all: -y -x c b a
reverse options: -x -y c b a
reverse non options: -x -y a b c
*/
#if __STDC__ || defined(PROTO)
static void exchange (char **argv);
#endif
static void
exchange (argv)
char **argv;
{
char *temp, **first, **last;
/* Reverse all the elements [first_nonopt, optind) */
first = &argv[first_nonopt];
last = &argv[optind-1];
while (first < last) {
temp = *first; *first = *last; *last = temp; first++; last--;
}
/* Put back the options in order */
first = &argv[first_nonopt];
first_nonopt += (optind - last_nonopt);
last = &argv[first_nonopt - 1];
while (first < last) {
temp = *first; *first = *last; *last = temp; first++; last--;
}
/* Put back the non options in order */
first = &argv[first_nonopt];
last_nonopt = optind;
last = &argv[last_nonopt-1];
while (first < last) {
temp = *first; *first = *last; *last = temp; first++; last--;
}
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return BAD_OPTION after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return BAD_OPTION.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
int option_index;
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIXLY_CORRECT") != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == NULL || *nextchar == '\0')
{
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
optind++;
last_nonopt = optind;
}
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
if (longopts != NULL
&& ((argv[optind][0] == '-'
&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
))
{
const struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
const struct option *pfound = NULL;
int indfound = 0;
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = longopts, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - nextchar == my_strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += my_strlen (nextchar);
optind++;
return BAD_OPTION;
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*s)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = s + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += my_strlen (nextchar);
return BAD_OPTION;
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += my_strlen (nextchar);
return optstring[0] == ':' ? ':' : BAD_OPTION;
}
}
nextchar += my_strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return BAD_OPTION;
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
#if 0
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
#endif
}
optopt = c;
return BAD_OPTION;
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
#if 0
fprintf (stderr, "%s: option `-%c' requires an argument\n",
argv[0], c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
#endif
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = BAD_OPTION;
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case BAD_OPTION:
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

View file

@ -0,0 +1,130 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __MacOSX__
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#endif
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
//#if __STDC__ || defined(PROTO)
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#endif /* not __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
//#else /* not __STDC__ */
extern int getopt (int argc, char *const *argv, const char *shortopts);
//extern int getopt_long ();
//extern int getopt_long_only ();
//extern int _getopt_internal ();
//#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,54 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifndef __ID3V2TAG_H__
#define __ID3V2TAG_H__
void GetID3FileTitle(char *filename, char *title, char *format);
void FillID3List(HWND hwndDlg, HWND hwndList, char *filename);
void List_OnGetDispInfo(LV_DISPINFO *pnmv);
BOOL List_EditData(HWND hwndApp, HWND hwndList);
void List_SaveID3(HWND hwndApp, HWND hwndList, char *filename);
BOOL List_DeleteSelected(HWND hwndApp, HWND hwndList);
BOOL List_AddFrame(HWND hwndApp, HWND hwndList);
BOOL List_AddStandardFrames(HWND hwndApp, HWND hwndList);
void AddFrameFromRAWData(HWND hwndList, int frameId, LPSTR data1, LPSTR data2);
HINSTANCE hInstance_for_id3editor;
typedef struct ID3GENRES_TAG
{
BYTE id;
char name[30];
} ID3GENRES;
typedef struct id3item_tag {
int frameId;
LPSTR aCols[2];
} ID3ITEM;
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
/*****************************************************************************
* drms.h : DRMS
*****************************************************************************
* Copyright (C) 2004 VideoLAN
* $Id$
*
* Author: Jon Lech Johansen <jon-vl@nanocrew.net>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
extern void *drms_alloc( char *psz_homedir );
extern void drms_free( void *p_drms );
extern int drms_init( void *p_drms, uint32_t i_type,
uint8_t *p_info, uint32_t i_len );
extern void drms_decrypt( void *p_drms, uint32_t *p_buffer,
uint32_t i_len );

View file

@ -0,0 +1,288 @@
/*****************************************************************************
* drmstables.h : AES/Rijndael block cipher and miscellaneous tables
*****************************************************************************
* Copyright (C) 2004 VideoLAN
* $Id$
*
* Author: Jon Lech Johansen <jon-vl@nanocrew.net>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define AES_ROR( x, n ) (((x) << (32-(n))) | ((x) >> (n)))
#define AES_XOR_ROR( p_table, p_tmp ) \
( p_table[ (p_tmp[ t > 2 ? t - 3 : t + 1 ] >> 24) & 0xFF ] \
^ AES_ROR( p_table[ (p_tmp[ t > 1 ? t - 2 : t + 2 ] >> 16) & 0xFF ], 8 ) \
^ AES_ROR( p_table[ (p_tmp[ t > 0 ? t - 1 : t + 3 ] >> 8) & 0xFF ], 16 ) \
^ AES_ROR( p_table[ p_tmp[ t ] & 0xFF ], 24 ) )
#define AES_KEY_COUNT 10
static uint32_t const p_aes_table[ AES_KEY_COUNT ] =
{
0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
0x00000040, 0x00000080, 0x0000001b, 0x00000036
};
static uint32_t const p_aes_encrypt[ 256 ] =
{
0x63000000, 0x7c000000, 0x77000000, 0x7b000000, 0xf2000000, 0x6b000000,
0x6f000000, 0xc5000000, 0x30000000, 0x01000000, 0x67000000, 0x2b000000,
0xfe000000, 0xd7000000, 0xab000000, 0x76000000, 0xca000000, 0x82000000,
0xc9000000, 0x7d000000, 0xfa000000, 0x59000000, 0x47000000, 0xf0000000,
0xad000000, 0xd4000000, 0xa2000000, 0xaf000000, 0x9c000000, 0xa4000000,
0x72000000, 0xc0000000, 0xb7000000, 0xfd000000, 0x93000000, 0x26000000,
0x36000000, 0x3f000000, 0xf7000000, 0xcc000000, 0x34000000, 0xa5000000,
0xe5000000, 0xf1000000, 0x71000000, 0xd8000000, 0x31000000, 0x15000000,
0x04000000, 0xc7000000, 0x23000000, 0xc3000000, 0x18000000, 0x96000000,
0x05000000, 0x9a000000, 0x07000000, 0x12000000, 0x80000000, 0xe2000000,
0xeb000000, 0x27000000, 0xb2000000, 0x75000000, 0x09000000, 0x83000000,
0x2c000000, 0x1a000000, 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000,
0x52000000, 0x3b000000, 0xd6000000, 0xb3000000, 0x29000000, 0xe3000000,
0x2f000000, 0x84000000, 0x53000000, 0xd1000000, 0x00000000, 0xed000000,
0x20000000, 0xfc000000, 0xb1000000, 0x5b000000, 0x6a000000, 0xcb000000,
0xbe000000, 0x39000000, 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000,
0xd0000000, 0xef000000, 0xaa000000, 0xfb000000, 0x43000000, 0x4d000000,
0x33000000, 0x85000000, 0x45000000, 0xf9000000, 0x02000000, 0x7f000000,
0x50000000, 0x3c000000, 0x9f000000, 0xa8000000, 0x51000000, 0xa3000000,
0x40000000, 0x8f000000, 0x92000000, 0x9d000000, 0x38000000, 0xf5000000,
0xbc000000, 0xb6000000, 0xda000000, 0x21000000, 0x10000000, 0xff000000,
0xf3000000, 0xd2000000, 0xcd000000, 0x0c000000, 0x13000000, 0xec000000,
0x5f000000, 0x97000000, 0x44000000, 0x17000000, 0xc4000000, 0xa7000000,
0x7e000000, 0x3d000000, 0x64000000, 0x5d000000, 0x19000000, 0x73000000,
0x60000000, 0x81000000, 0x4f000000, 0xdc000000, 0x22000000, 0x2a000000,
0x90000000, 0x88000000, 0x46000000, 0xee000000, 0xb8000000, 0x14000000,
0xde000000, 0x5e000000, 0x0b000000, 0xdb000000, 0xe0000000, 0x32000000,
0x3a000000, 0x0a000000, 0x49000000, 0x06000000, 0x24000000, 0x5c000000,
0xc2000000, 0xd3000000, 0xac000000, 0x62000000, 0x91000000, 0x95000000,
0xe4000000, 0x79000000, 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000,
0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000, 0x6c000000, 0x56000000,
0xf4000000, 0xea000000, 0x65000000, 0x7a000000, 0xae000000, 0x08000000,
0xba000000, 0x78000000, 0x25000000, 0x2e000000, 0x1c000000, 0xa6000000,
0xb4000000, 0xc6000000, 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000,
0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000, 0x70000000, 0x3e000000,
0xb5000000, 0x66000000, 0x48000000, 0x03000000, 0xf6000000, 0x0e000000,
0x61000000, 0x35000000, 0x57000000, 0xb9000000, 0x86000000, 0xc1000000,
0x1d000000, 0x9e000000, 0xe1000000, 0xf8000000, 0x98000000, 0x11000000,
0x69000000, 0xd9000000, 0x8e000000, 0x94000000, 0x9b000000, 0x1e000000,
0x87000000, 0xe9000000, 0xce000000, 0x55000000, 0x28000000, 0xdf000000,
0x8c000000, 0xa1000000, 0x89000000, 0x0d000000, 0xbf000000, 0xe6000000,
0x42000000, 0x68000000, 0x41000000, 0x99000000, 0x2d000000, 0x0f000000,
0xb0000000, 0x54000000, 0xbb000000, 0x16000000
};
static uint32_t const p_aes_itable[ 256 ] =
{
0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d,
0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02,
0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362, 0xde495ab1, 0x25671bba,
0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3,
0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58, 0x27dd71b9,
0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a,
0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08,
0x70586848, 0x8f19fd45, 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b,
0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479,
0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05, 0xd11f6234, 0xc48afea6,
0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, 0x0b39ec83, 0x40aaef60,
0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6,
0x91b58d54, 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8,
0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, 0x09838680, 0x3248ed2b,
0x1eac7011, 0x6c4e725a, 0xfdfbff0e, 0x0f563885, 0x3d1ed5ae, 0x3627392d,
0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757,
0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09, 0xf2adc78b,
0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f,
0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623,
0xb668fced, 0xb863f1e4, 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6,
0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9,
0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033, 0x87c74e49, 0xd9c1d138,
0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad,
0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8,
0x2e5ef739, 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859,
0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815,
0xbad99be7, 0x4ace366f, 0xead4099f, 0x29d67cb0, 0x31afb2a4, 0x2a31233f,
0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7,
0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c, 0x467f5165,
0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db,
0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13,
0xceee27a9, 0xb735c961, 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2,
0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2,
0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c, 0xd89ce4b4, 0x6490c156,
0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8
};
static uint32_t const p_aes_decrypt[ 256 ] =
{
0x52000000, 0x09000000, 0x6a000000, 0xd5000000, 0x30000000, 0x36000000,
0xa5000000, 0x38000000, 0xbf000000, 0x40000000, 0xa3000000, 0x9e000000,
0x81000000, 0xf3000000, 0xd7000000, 0xfb000000, 0x7c000000, 0xe3000000,
0x39000000, 0x82000000, 0x9b000000, 0x2f000000, 0xff000000, 0x87000000,
0x34000000, 0x8e000000, 0x43000000, 0x44000000, 0xc4000000, 0xde000000,
0xe9000000, 0xcb000000, 0x54000000, 0x7b000000, 0x94000000, 0x32000000,
0xa6000000, 0xc2000000, 0x23000000, 0x3d000000, 0xee000000, 0x4c000000,
0x95000000, 0x0b000000, 0x42000000, 0xfa000000, 0xc3000000, 0x4e000000,
0x08000000, 0x2e000000, 0xa1000000, 0x66000000, 0x28000000, 0xd9000000,
0x24000000, 0xb2000000, 0x76000000, 0x5b000000, 0xa2000000, 0x49000000,
0x6d000000, 0x8b000000, 0xd1000000, 0x25000000, 0x72000000, 0xf8000000,
0xf6000000, 0x64000000, 0x86000000, 0x68000000, 0x98000000, 0x16000000,
0xd4000000, 0xa4000000, 0x5c000000, 0xcc000000, 0x5d000000, 0x65000000,
0xb6000000, 0x92000000, 0x6c000000, 0x70000000, 0x48000000, 0x50000000,
0xfd000000, 0xed000000, 0xb9000000, 0xda000000, 0x5e000000, 0x15000000,
0x46000000, 0x57000000, 0xa7000000, 0x8d000000, 0x9d000000, 0x84000000,
0x90000000, 0xd8000000, 0xab000000, 0x00000000, 0x8c000000, 0xbc000000,
0xd3000000, 0x0a000000, 0xf7000000, 0xe4000000, 0x58000000, 0x05000000,
0xb8000000, 0xb3000000, 0x45000000, 0x06000000, 0xd0000000, 0x2c000000,
0x1e000000, 0x8f000000, 0xca000000, 0x3f000000, 0x0f000000, 0x02000000,
0xc1000000, 0xaf000000, 0xbd000000, 0x03000000, 0x01000000, 0x13000000,
0x8a000000, 0x6b000000, 0x3a000000, 0x91000000, 0x11000000, 0x41000000,
0x4f000000, 0x67000000, 0xdc000000, 0xea000000, 0x97000000, 0xf2000000,
0xcf000000, 0xce000000, 0xf0000000, 0xb4000000, 0xe6000000, 0x73000000,
0x96000000, 0xac000000, 0x74000000, 0x22000000, 0xe7000000, 0xad000000,
0x35000000, 0x85000000, 0xe2000000, 0xf9000000, 0x37000000, 0xe8000000,
0x1c000000, 0x75000000, 0xdf000000, 0x6e000000, 0x47000000, 0xf1000000,
0x1a000000, 0x71000000, 0x1d000000, 0x29000000, 0xc5000000, 0x89000000,
0x6f000000, 0xb7000000, 0x62000000, 0x0e000000, 0xaa000000, 0x18000000,
0xbe000000, 0x1b000000, 0xfc000000, 0x56000000, 0x3e000000, 0x4b000000,
0xc6000000, 0xd2000000, 0x79000000, 0x20000000, 0x9a000000, 0xdb000000,
0xc0000000, 0xfe000000, 0x78000000, 0xcd000000, 0x5a000000, 0xf4000000,
0x1f000000, 0xdd000000, 0xa8000000, 0x33000000, 0x88000000, 0x07000000,
0xc7000000, 0x31000000, 0xb1000000, 0x12000000, 0x10000000, 0x59000000,
0x27000000, 0x80000000, 0xec000000, 0x5f000000, 0x60000000, 0x51000000,
0x7f000000, 0xa9000000, 0x19000000, 0xb5000000, 0x4a000000, 0x0d000000,
0x2d000000, 0xe5000000, 0x7a000000, 0x9f000000, 0x93000000, 0xc9000000,
0x9c000000, 0xef000000, 0xa0000000, 0xe0000000, 0x3b000000, 0x4d000000,
0xae000000, 0x2a000000, 0xf5000000, 0xb0000000, 0xc8000000, 0xeb000000,
0xbb000000, 0x3c000000, 0x83000000, 0x53000000, 0x99000000, 0x61000000,
0x17000000, 0x2b000000, 0x04000000, 0x7e000000, 0xba000000, 0x77000000,
0xd6000000, 0x26000000, 0xe1000000, 0x69000000, 0x14000000, 0x63000000,
0x55000000, 0x21000000, 0x0c000000, 0x7d000000
};
static uint16_t const p_shuffle_xor[ 256 ] =
{
0x00d1, 0x0315, 0x1a32, 0x19ec, 0x1bbb, 0x1d6f, 0x14fe, 0x0e9e,
0x029e, 0x1b8f, 0x0b70, 0x033a, 0x188e, 0x1d18, 0x0bd8, 0x0edb,
0x0c64, 0x1c2b, 0x149c, 0x047b, 0x1064, 0x1c7c, 0x118d, 0x1355,
0x0ae5, 0x0f18, 0x016f, 0x17d6, 0x1595, 0x0084, 0x0616, 0x1ccd,
0x1d94, 0x0618, 0x182c, 0x195b, 0x196d, 0x0394, 0x07db, 0x0287,
0x1636, 0x0b81, 0x1519, 0x0df9, 0x1ba3, 0x1cc3, 0x0ee2, 0x1434,
0x1457, 0x0ced, 0x0f7d, 0x0d7b, 0x0b9e, 0x0d13, 0x13d7, 0x18d0,
0x1259, 0x1977, 0x0606, 0x1e80, 0x05f2, 0x06b8, 0x1f07, 0x1365,
0x0334, 0x0e30, 0x195f, 0x15f1, 0x058e, 0x0aa8, 0x045a, 0x0465,
0x0b3e, 0x071e, 0x0a36, 0x105c, 0x01ac, 0x1a1e, 0x04e4, 0x056b,
0x12bf, 0x0da2, 0x0b41, 0x0eaf, 0x034f, 0x0181, 0x04e2, 0x002b,
0x12e6, 0x01be, 0x10e8, 0x128f, 0x0eb2, 0x1369, 0x05be, 0x1a59,
0x117e, 0x047c, 0x1e86, 0x056a, 0x0da7, 0x0d61, 0x03fc, 0x1e6e,
0x1d0c, 0x1e6d, 0x14bf, 0x0c50, 0x063a, 0x1b47, 0x17ae, 0x1321,
0x041b, 0x0a24, 0x0d4d, 0x1f2b, 0x1cb6, 0x1bed, 0x1549, 0x03a7,
0x0254, 0x006c, 0x0c9e, 0x0f73, 0x006c, 0x0008, 0x11f9, 0x0dd5,
0x0bcf, 0x0af9, 0x1dfe, 0x0341, 0x0e49, 0x0d38, 0x17cb, 0x1513,
0x0e96, 0x00ed, 0x0556, 0x1b28, 0x100c, 0x19d8, 0x14fa, 0x028c,
0x1c60, 0x1232, 0x13d3, 0x0d00, 0x1534, 0x192c, 0x14b5, 0x1cf2,
0x0504, 0x0b5b, 0x1ecf, 0x0423, 0x183b, 0x06b0, 0x169e, 0x1066,
0x04cb, 0x08a2, 0x1b4a, 0x1254, 0x198d, 0x1044, 0x0236, 0x1bd8,
0x18a1, 0x03ff, 0x1a0d, 0x0277, 0x0c2d, 0x17c9, 0x007c, 0x116e,
0x048a, 0x1eaf, 0x0922, 0x0c45, 0x0766, 0x1e5f, 0x1a28, 0x0120,
0x1c15, 0x034c, 0x0508, 0x0e73, 0x0879, 0x0441, 0x09ae, 0x132f,
0x14fe, 0x0413, 0x0a9d, 0x1727, 0x01d7, 0x1a2b, 0x0474, 0x18f0,
0x1f3b, 0x14f5, 0x1071, 0x0895, 0x1071, 0x18ff, 0x18e3, 0x0eb9,
0x0ba9, 0x0961, 0x1599, 0x019e, 0x1d12, 0x1baa, 0x1e94, 0x1921,
0x14dc, 0x124e, 0x0a25, 0x03ab, 0x1cc0, 0x1ebb, 0x0b4b, 0x16e5,
0x11ea, 0x0d78, 0x1bb3, 0x1ba7, 0x1510, 0x1b7b, 0x0c64, 0x1995,
0x1a58, 0x1651, 0x1964, 0x147a, 0x15f2, 0x11bb, 0x1654, 0x166e,
0x0ea9, 0x1de1, 0x1443, 0x13c5, 0x00e1, 0x0b2f, 0x0b6f, 0x0a37,
0x18ac, 0x08e6, 0x06f0, 0x136e, 0x0853, 0x0b2e, 0x0813, 0x10d6
};
static uint16_t const p_shuffle_sub[ 256 ] =
{
0x067a, 0x0c7d, 0x0b4f, 0x127d, 0x0bd6, 0x04ac, 0x16e0, 0x1730,
0x0587, 0x0afb, 0x1ac3, 0x0120, 0x14b5, 0x0f67, 0x11de, 0x0961,
0x1127, 0x1a68, 0x07f0, 0x17d0, 0x1a6f, 0x1f3b, 0x01ef, 0x0919,
0x131e, 0x0f90, 0x19e9, 0x18a8, 0x0cb2, 0x1ad0, 0x0c66, 0x0378,
0x03b0, 0x01be, 0x1866, 0x1159, 0x197c, 0x1105, 0x010b, 0x0353,
0x1abb, 0x09a6, 0x028a, 0x1bad, 0x1b20, 0x0455, 0x0f57, 0x0588,
0x1491, 0x0a1d, 0x0f04, 0x0650, 0x191e, 0x1e0e, 0x174b, 0x016b,
0x051f, 0x0532, 0x00df, 0x1aea, 0x0005, 0x0e1b, 0x0ff6, 0x08d8,
0x14b4, 0x086a, 0x0c20, 0x0149, 0x1971, 0x0f26, 0x1852, 0x017d,
0x1228, 0x0352, 0x0a44, 0x1330, 0x18df, 0x1e38, 0x01bc, 0x0bac,
0x1a48, 0x021f, 0x02f7, 0x0c31, 0x0bc4, 0x1e75, 0x105c, 0x13e3,
0x0b20, 0x03a1, 0x1af3, 0x1a36, 0x0e34, 0x181f, 0x09bd, 0x122b,
0x0ee0, 0x163b, 0x0be7, 0x103d, 0x1075, 0x1e9d, 0x02af, 0x0ba2,
0x1daa, 0x0cf1, 0x04b6, 0x0598, 0x06a1, 0x0d33, 0x1cfe, 0x04ee,
0x1bad, 0x07c8, 0x1a48, 0x05e6, 0x031f, 0x0e0a, 0x0326, 0x1650,
0x0526, 0x0b4e, 0x08fc, 0x0e4d, 0x0832, 0x06ea, 0x09bf, 0x0993,
0x09eb, 0x0f31, 0x071b, 0x14d5, 0x11ca, 0x0722, 0x120d, 0x014c,
0x1993, 0x0ae4, 0x1ccb, 0x04e9, 0x0aee, 0x1708, 0x0c3d, 0x12f2,
0x1a19, 0x07c1, 0x05a7, 0x0744, 0x1606, 0x1a9b, 0x042d, 0x1bfc,
0x1841, 0x0c3c, 0x0ffe, 0x1ab1, 0x1416, 0x18a9, 0x0320, 0x1ec2,
0x0ae7, 0x11c6, 0x124a, 0x11df, 0x0f81, 0x06cf, 0x0ed9, 0x0253,
0x1d2b, 0x0349, 0x0805, 0x08b3, 0x1052, 0x12cf, 0x0a44, 0x0ea6,
0x03bf, 0x1d90, 0x0ef8, 0x0657, 0x156d, 0x0405, 0x10be, 0x091f,
0x1c82, 0x1725, 0x19ef, 0x0b8c, 0x04d9, 0x02c7, 0x025a, 0x1b89,
0x0f5c, 0x013d, 0x02f7, 0x12e3, 0x0bc5, 0x1b56, 0x0848, 0x0239,
0x0fcf, 0x03a4, 0x092d, 0x1354, 0x1d83, 0x01bd, 0x071a, 0x0af1,
0x0875, 0x0793, 0x1b41, 0x1782, 0x0def, 0x1d20, 0x13be, 0x0095,
0x1650, 0x19d4, 0x0de3, 0x0980, 0x18f2, 0x0ca3, 0x0098, 0x149a,
0x0b81, 0x0ad2, 0x1bba, 0x1a02, 0x027b, 0x1906, 0x07f5, 0x1cae,
0x0c3f, 0x02f6, 0x1298, 0x175e, 0x15b2, 0x13d8, 0x14cc, 0x161a,
0x0a42, 0x15f3, 0x0870, 0x1c1d, 0x1203, 0x18b1, 0x1738, 0x1954,
0x1143, 0x1ae8, 0x1d9d, 0x155b, 0x11e8, 0x0ed9, 0x06f7, 0x04ca
};
static uint16_t const p_shuffle_add[ 256 ] =
{
0x0706, 0x175a, 0x0def, 0x1e72, 0x0297, 0x1b0e, 0x1d5a, 0x15b8,
0x13e2, 0x1347, 0x10c6, 0x0b4f, 0x0629, 0x0a75, 0x0a9b, 0x0f55,
0x1a69, 0x09bf, 0x0ba6, 0x1582, 0x1086, 0x1921, 0x01cb, 0x1c6a,
0x0ff5, 0x00f7, 0x0a67, 0x0a1e, 0x1838, 0x0196, 0x10d6, 0x0c7a,
0x180e, 0x038d, 0x1add, 0x0684, 0x154a, 0x0ab0, 0x18a4, 0x0d73,
0x1641, 0x0ec6, 0x09f1, 0x1a62, 0x0414, 0x162a, 0x194e, 0x1ec9,
0x022f, 0x0296, 0x1104, 0x14fc, 0x096c, 0x1d02, 0x09bd, 0x027c,
0x080e, 0x1324, 0x128c, 0x0dc1, 0x00b9, 0x17f2, 0x0cbc, 0x0f97,
0x1b93, 0x1c3c, 0x0415, 0x0395, 0x0c7a, 0x06cc, 0x0d4b, 0x16e2,
0x04a2, 0x0dab, 0x1228, 0x012b, 0x0896, 0x0012, 0x1cd6, 0x1dac,
0x080d, 0x0446, 0x047a, 0x00ad, 0x029e, 0x0686, 0x17c3, 0x1466,
0x0d16, 0x1896, 0x076e, 0x00cd, 0x17dc, 0x1e9f, 0x1a7c, 0x02bb,
0x0d06, 0x112b, 0x14cb, 0x0a03, 0x1541, 0x1290, 0x0f6d, 0x1503,
0x084b, 0x0382, 0x1a3f, 0x0371, 0x1977, 0x0b67, 0x0cad, 0x1df8,
0x1ce3, 0x1306, 0x13f8, 0x1163, 0x1b0b, 0x00bd, 0x0bf0, 0x1a4f,
0x16f7, 0x0b4f, 0x0cf8, 0x1254, 0x0541, 0x100d, 0x0296, 0x0410,
0x1a2b, 0x1169, 0x17d9, 0x0819, 0x03d6, 0x0d03, 0x194d, 0x184a,
0x07ca, 0x1989, 0x0fad, 0x011c, 0x1c71, 0x0ef6, 0x0dc8, 0x0f2f,
0x0fa5, 0x11be, 0x0f3b, 0x1d52, 0x0de2, 0x016e, 0x1ad1, 0x0c4a,
0x1bc2, 0x0ac9, 0x1485, 0x1bee, 0x0949, 0x1a79, 0x1894, 0x12bb,
0x17b6, 0x14f5, 0x16b1, 0x142c, 0x1301, 0x03ef, 0x16ff, 0x0d37,
0x0d78, 0x01ff, 0x00d6, 0x1053, 0x1a2a, 0x0f61, 0x1352, 0x0c7f,
0x137f, 0x09c4, 0x1d96, 0x021d, 0x1037, 0x1b19, 0x10ef, 0x14e4,
0x02a0, 0x0236, 0x0a5d, 0x1519, 0x141c, 0x1399, 0x007e, 0x1e74,
0x0941, 0x1b3c, 0x0062, 0x0371, 0x09ad, 0x08e8, 0x0a24, 0x0b97,
0x1ed2, 0x0889, 0x136b, 0x0006, 0x1c4c, 0x0444, 0x06f8, 0x0dfb,
0x1d0f, 0x198d, 0x0700, 0x0afc, 0x1781, 0x12f3, 0x10da, 0x1f19,
0x1055, 0x0dc9, 0x1860, 0x012b, 0x05bf, 0x082d, 0x0c17, 0x1941,
0x0359, 0x1232, 0x104c, 0x0762, 0x0897, 0x1d6c, 0x030f, 0x1a36,
0x16b0, 0x094d, 0x1782, 0x036f, 0x0eea, 0x06e6, 0x0d00, 0x0187,
0x17e2, 0x05e5, 0x19fa, 0x1950, 0x146a, 0x0b2a, 0x0512, 0x0ee0,
0x1e27, 0x112d, 0x1df0, 0x0b13, 0x0378, 0x1dd0, 0x00c1, 0x01e6
};

View file

@ -0,0 +1,901 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#include <stdlib.h>
#ifndef _WIN32
#include "config.h"
#else
#include <tchar.h>
#ifdef ITUNES_DRM
#include <shlobj.h>
#endif
#include <windows.h>
#endif
#ifdef HAVE_GETPWUID
# include <pwd.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include "mp4ffint.h"
#include "drms.h"
/* parse atom header size */
static int32_t mp4ff_atom_get_size(const int8_t *data)
{
uint32_t result;
uint32_t a, b, c, d;
a = (uint8_t)data[0];
b = (uint8_t)data[1];
c = (uint8_t)data[2];
d = (uint8_t)data[3];
result = (a<<24) | (b<<16) | (c<<8) | d;
//if (result > 0 && result < 8) result = 8;
return (int32_t)result;
}
/* comnapre 2 atom names, returns 1 for equal, 0 for unequal */
static int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1, const int8_t c1, const int8_t d1,
const int8_t a2, const int8_t b2, const int8_t c2, const int8_t d2)
{
if (a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2)
return 1;
else
return 0;
}
static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b,
const int8_t c, const int8_t d)
{
if (a == 'm')
{
if (mp4ff_atom_compare(a,b,c,d, 'm','o','o','v'))
return ATOM_MOOV;
else if (mp4ff_atom_compare(a,b,c,d, 'm','i','n','f'))
return ATOM_MINF;
else if (mp4ff_atom_compare(a,b,c,d, 'm','d','i','a'))
return ATOM_MDIA;
else if (mp4ff_atom_compare(a,b,c,d, 'm','d','a','t'))
return ATOM_MDAT;
else if (mp4ff_atom_compare(a,b,c,d, 'm','d','h','d'))
return ATOM_MDHD;
else if (mp4ff_atom_compare(a,b,c,d, 'm','v','h','d'))
return ATOM_MVHD;
else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','a'))
return ATOM_MP4A;
else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','v'))
return ATOM_MP4V;
else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','s'))
return ATOM_MP4S;
else if (mp4ff_atom_compare(a,b,c,d, 'm','e','t','a'))
return ATOM_META;
} else if (a == 't') {
if (mp4ff_atom_compare(a,b,c,d, 't','r','a','k'))
return ATOM_TRAK;
else if (mp4ff_atom_compare(a,b,c,d, 't','k','h','d'))
return ATOM_TKHD;
else if (mp4ff_atom_compare(a,b,c,d, 't','r','e','f'))
return ATOM_TREF;
else if (mp4ff_atom_compare(a,b,c,d, 't','r','k','n'))
return ATOM_TRACK;
else if (mp4ff_atom_compare(a,b,c,d, 't','m','p','o'))
return ATOM_TEMPO;
} else if (a == 's') {
if (mp4ff_atom_compare(a,b,c,d, 's','t','b','l'))
return ATOM_STBL;
else if (mp4ff_atom_compare(a,b,c,d, 's','m','h','d'))
return ATOM_SMHD;
else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','d'))
return ATOM_STSD;
else if (mp4ff_atom_compare(a,b,c,d, 's','t','t','s'))
return ATOM_STTS;
else if (mp4ff_atom_compare(a,b,c,d, 's','t','c','o'))
return ATOM_STCO;
else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','c'))
return ATOM_STSC;
else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','z'))
return ATOM_STSZ;
else if (mp4ff_atom_compare(a,b,c,d, 's','t','z','2'))
return ATOM_STZ2;
else if (mp4ff_atom_compare(a,b,c,d, 's','k','i','p'))
return ATOM_SKIP;
else if (mp4ff_atom_compare(a,b,c,d, 's','i','n','f'))
return ATOM_SINF;
else if (mp4ff_atom_compare(a,b,c,d, 's','c','h','i'))
return ATOM_SCHI;
} else if (a == '©') {
if (mp4ff_atom_compare(a,b,c,d, '©','n','a','m'))
return ATOM_TITLE;
else if (mp4ff_atom_compare(a,b,c,d, '©','A','R','T'))
return ATOM_ARTIST;
else if (mp4ff_atom_compare(a,b,c,d, '©','w','r','t'))
return ATOM_WRITER;
else if (mp4ff_atom_compare(a,b,c,d, '©','a','l','b'))
return ATOM_ALBUM;
else if (mp4ff_atom_compare(a,b,c,d, '©','d','a','y'))
return ATOM_DATE;
else if (mp4ff_atom_compare(a,b,c,d, '©','t','o','o'))
return ATOM_TOOL;
else if (mp4ff_atom_compare(a,b,c,d, '©','c','m','t'))
return ATOM_COMMENT;
else if (mp4ff_atom_compare(a,b,c,d, '©','g','e','n'))
return ATOM_GENRE1;
}
if (mp4ff_atom_compare(a,b,c,d, 'e','d','t','s'))
return ATOM_EDTS;
else if (mp4ff_atom_compare(a,b,c,d, 'e','s','d','s'))
return ATOM_ESDS;
else if (mp4ff_atom_compare(a,b,c,d, 'f','t','y','p'))
return ATOM_FTYP;
else if (mp4ff_atom_compare(a,b,c,d, 'f','r','e','e'))
return ATOM_FREE;
else if (mp4ff_atom_compare(a,b,c,d, 'h','m','h','d'))
return ATOM_HMHD;
else if (mp4ff_atom_compare(a,b,c,d, 'v','m','h','d'))
return ATOM_VMHD;
else if (mp4ff_atom_compare(a,b,c,d, 'u','d','t','a'))
return ATOM_UDTA;
else if (mp4ff_atom_compare(a,b,c,d, 'i','l','s','t'))
return ATOM_ILST;
else if (mp4ff_atom_compare(a,b,c,d, 'n','a','m','e'))
return ATOM_NAME;
else if (mp4ff_atom_compare(a,b,c,d, 'd','a','t','a'))
return ATOM_DATA;
else if (mp4ff_atom_compare(a,b,c,d, 'd','i','s','k'))
return ATOM_DISC;
else if (mp4ff_atom_compare(a,b,c,d, 'g','n','r','e'))
return ATOM_GENRE2;
else if (mp4ff_atom_compare(a,b,c,d, 'c','o','v','r'))
return ATOM_COVER;
else if (mp4ff_atom_compare(a,b,c,d, 'c','p','i','l'))
return ATOM_COMPILATION;
else if (mp4ff_atom_compare(a,b,c,d, 'c','t','t','s'))
return ATOM_CTTS;
else if (mp4ff_atom_compare(a,b,c,d, 'd','r','m','s'))
return ATOM_DRMS;
else if (mp4ff_atom_compare(a,b,c,d, 'f','r','m','a'))
return ATOM_FRMA;
else if (mp4ff_atom_compare(a,b,c,d, 'p','r','i','v'))
return ATOM_PRIV;
else if (mp4ff_atom_compare(a,b,c,d, 'i','v','i','v'))
return ATOM_IVIV;
else if (mp4ff_atom_compare(a,b,c,d, 'u','s','e','r'))
return ATOM_USER;
else if (mp4ff_atom_compare(a,b,c,d, 'k','e','y',' '))
return ATOM_KEY;
else
return ATOM_UNKNOWN;
}
/* read atom header, return atom size, atom size is with header included */
uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size)
{
uint64_t size;
int32_t ret;
int8_t atom_header[8];
ret = mp4ff_read_data(f, atom_header, 8);
if (ret != 8)
return 0;
size = mp4ff_atom_get_size(atom_header);
*header_size = 8;
/* check for 64 bit atom size */
if (size == 1)
{
*header_size = 16;
size = mp4ff_read_int64(f);
}
//printf("%c%c%c%c\n", atom_header[4], atom_header[5], atom_header[6], atom_header[7]);
*atom_type = mp4ff_atom_name_to_type(atom_header[4], atom_header[5], atom_header[6], atom_header[7]);
return size;
}
static int32_t mp4ff_read_stsz(mp4ff_t *f)
{
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
f->track[f->total_tracks - 1]->stsz_sample_size = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->stsz_sample_count = mp4ff_read_int32(f);
if (f->track[f->total_tracks - 1]->stsz_sample_size == 0)
{
int32_t i;
f->track[f->total_tracks - 1]->stsz_table =
(int32_t*)malloc(f->track[f->total_tracks - 1]->stsz_sample_count*sizeof(int32_t));
for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count; i++)
{
f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f);
}
}
return 0;
}
static int32_t mp4ff_read_esds(mp4ff_t *f)
{
uint8_t tag;
uint32_t temp;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
/* get and verify ES_DescrTag */
tag = mp4ff_read_char(f);
if (tag == 0x03)
{
/* read length */
if (mp4ff_read_mp4_descr_length(f) < 5 + 15)
{
return 1;
}
/* skip 3 bytes */
mp4ff_read_int24(f);
} else {
/* skip 2 bytes */
mp4ff_read_int16(f);
}
/* get and verify DecoderConfigDescrTab */
if (mp4ff_read_char(f) != 0x04)
{
return 1;
}
/* read length */
temp = mp4ff_read_mp4_descr_length(f);
if (temp < 13) return 1;
f->track[f->total_tracks - 1]->audioType = mp4ff_read_char(f);
mp4ff_read_int32(f);//0x15000414 ????
f->track[f->total_tracks - 1]->maxBitrate = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->avgBitrate = mp4ff_read_int32(f);
/* get and verify DecSpecificInfoTag */
if (mp4ff_read_char(f) != 0x05)
{
return 1;
}
/* read length */
f->track[f->total_tracks - 1]->decoderConfigLen = mp4ff_read_mp4_descr_length(f);
if (f->track[f->total_tracks - 1]->decoderConfig)
free(f->track[f->total_tracks - 1]->decoderConfig);
f->track[f->total_tracks - 1]->decoderConfig = malloc(f->track[f->total_tracks - 1]->decoderConfigLen);
if (f->track[f->total_tracks - 1]->decoderConfig)
{
mp4ff_read_data(f, f->track[f->total_tracks - 1]->decoderConfig, f->track[f->total_tracks - 1]->decoderConfigLen);
} else {
f->track[f->total_tracks - 1]->decoderConfigLen = 0;
}
/* will skip the remainder of the atom */
return 0;
}
static int32_t mp4ff_read_mp4a(mp4ff_t *f)
{
uint64_t size;
int32_t i;
uint8_t atom_type = 0;
uint8_t header_size = 0;
for (i = 0; i < 6; i++)
{
mp4ff_read_char(f); /* reserved */
}
/* data_reference_index */ mp4ff_read_int16(f);
mp4ff_read_int32(f); /* reserved */
mp4ff_read_int32(f); /* reserved */
f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f);
f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f);
mp4ff_read_int16(f);
mp4ff_read_int16(f);
f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f);
mp4ff_read_int16(f);
size = mp4ff_atom_read_header(f, &atom_type, &header_size);
if (atom_type == ATOM_ESDS)
{
mp4ff_read_esds(f);
}
return 0;
}
#ifdef ITUNES_DRM
char *GetHomeDir( void )
{
char *p_tmp, *p_homedir = NULL;
#if defined(HAVE_GETPWUID)
struct passwd *p_pw = NULL;
#endif
#if defined(_WIN32) || defined(UNDER_CE)
typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
LPSTR );
# define CSIDL_FLAG_CREATE 0x8000
# define CSIDL_APPDATA 0x1A
# define SHGFP_TYPE_CURRENT 0
HINSTANCE shfolder_dll;
SHGETFOLDERPATH SHGetFolderPath ;
/* load the shfolder dll to retrieve SHGetFolderPath */
if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
{
SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
_T("SHGetFolderPathA") );
if ( SHGetFolderPath != NULL )
{
p_homedir = (char *)malloc( MAX_PATH );
if( !p_homedir )
{
return NULL;
}
/* get the "Application Data" folder for the current user */
if( S_OK == SHGetFolderPath( NULL,
CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, SHGFP_TYPE_CURRENT,
p_homedir ) )
{
FreeLibrary( shfolder_dll );
return p_homedir;
}
free( p_homedir );
}
FreeLibrary( shfolder_dll );
}
#endif
#if defined(HAVE_GETPWUID)
if( ( p_pw = getpwuid( getuid() ) ) == NULL )
#endif
{
if( ( p_tmp = getenv( "HOME" ) ) == NULL )
{
if( ( p_tmp = getenv( "TMP" ) ) == NULL )
{
p_tmp = "/tmp";
}
}
p_homedir = strdup( p_tmp );
}
#if defined(HAVE_GETPWUID)
else
{
p_homedir = strdup( p_pw->pw_dir );
}
#endif
return p_homedir;
}
static int32_t mp4ff_read_drms(mp4ff_t *f, uint64_t skip)
{
uint64_t size;
int32_t i;
uint8_t atom_type = 0;
uint8_t header_size = 0;
f->track[f->total_tracks - 1]->p_drms = drms_alloc( GetHomeDir() );
for (i = 0; i < 6; i++)
{
mp4ff_read_char(f); /* reserved */
}
/* data_reference_index */ mp4ff_read_int16(f);
mp4ff_read_int32(f); /* reserved */
mp4ff_read_int32(f); /* reserved */
f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f);
f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f);
mp4ff_read_int16(f);
mp4ff_read_int16(f);
f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f);
mp4ff_read_int16(f);
size = mp4ff_atom_read_header(f, &atom_type, &header_size);
if (atom_type == ATOM_ESDS)
{
mp4ff_read_esds(f);
}
mp4ff_set_position(f, skip+size+28);
size = mp4ff_atom_read_header(f, &atom_type, &header_size);
if (atom_type == ATOM_SINF)
{
parse_sub_atoms(f, size-header_size,0);
}
return 0;
}
static int32_t mp4ff_read_frma(mp4ff_t *f)
{
uint8_t atom_type;
int8_t type[4];
mp4ff_read_data(f, type, 4);
atom_type = mp4ff_atom_name_to_type(type[0], type[1], type[2], type[3]);
if (atom_type == ATOM_MP4A)
{
f->track[f->total_tracks - 1]->type = TRACK_AUDIO;
} else if (atom_type == ATOM_MP4V) {
f->track[f->total_tracks - 1]->type = TRACK_VIDEO;
} else if (atom_type == ATOM_MP4S) {
f->track[f->total_tracks - 1]->type = TRACK_SYSTEM;
} else {
f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
}
return 0;
}
static int32_t mp4ff_read_name(mp4ff_t *f, uint64_t size)
{
uint8_t *data = malloc(size);
mp4ff_read_data(f, data, size);
if (f->track[f->total_tracks - 1]->p_drms != NULL)
{
drms_init(f->track[f->total_tracks - 1]->p_drms,
FOURCC_name, data, strlen(data) );
}
if (data)
free(data);
return 0;
}
static int32_t mp4ff_read_priv(mp4ff_t *f, uint64_t size)
{
uint8_t *data = malloc(size);
mp4ff_read_data(f, data, size);
if (f->track[f->total_tracks - 1]->p_drms != 0)
{
drms_init(f->track[f->total_tracks - 1]->p_drms,
FOURCC_priv, data, size );
}
if (data)
free(data);
return 0;
}
static int32_t mp4ff_read_iviv(mp4ff_t *f, uint64_t size)
{
uint8_t *data = malloc(size);
mp4ff_read_data(f, data, size);
if (f->track[f->total_tracks - 1]->p_drms != 0)
{
drms_init(f->track[f->total_tracks - 1]->p_drms,
FOURCC_iviv, data, sizeof(uint32_t) * 4 );
}
if (data)
free(data);
return 0;
}
static int32_t mp4ff_read_user(mp4ff_t *f, uint64_t size)
{
uint8_t *data = malloc(size);
mp4ff_read_data(f, data, size);
if (f->track[f->total_tracks - 1]->p_drms != 0)
{
drms_init(f->track[f->total_tracks - 1]->p_drms,
FOURCC_user, data, size );
}
if (data)
free(data);
return 0;
}
static int32_t mp4ff_read_key(mp4ff_t *f, uint64_t size)
{
uint8_t *data = malloc(size);
mp4ff_read_data(f, data, size);
if (f->track[f->total_tracks - 1]->p_drms != 0)
{
drms_init(f->track[f->total_tracks - 1]->p_drms,
FOURCC_key, data, size );
}
if (data)
free(data);
return 0;
}
#endif
static int32_t mp4ff_read_stsd(mp4ff_t *f)
{
int32_t i;
uint8_t header_size = 0;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f);
for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count; i++)
{
uint64_t skip = mp4ff_position(f);
uint64_t size;
uint8_t atom_type = 0;
size = mp4ff_atom_read_header(f, &atom_type, &header_size);
skip += size;
if (atom_type == ATOM_MP4A)
{
f->track[f->total_tracks - 1]->type = TRACK_AUDIO;
mp4ff_read_mp4a(f);
} else if (atom_type == ATOM_MP4V) {
f->track[f->total_tracks - 1]->type = TRACK_VIDEO;
} else if (atom_type == ATOM_MP4S) {
f->track[f->total_tracks - 1]->type = TRACK_SYSTEM;
#ifdef ITUNES_DRM
} else if (atom_type == ATOM_DRMS) {
// track type is read from the "frma" atom
f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
mp4ff_read_drms(f, skip-size+header_size);
#endif
} else {
f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
}
mp4ff_set_position(f, skip);
}
return 0;
}
static int32_t mp4ff_read_stsc(mp4ff_t *f)
{
int32_t i;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->stsc_first_chunk =
(int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t));
f->track[f->total_tracks - 1]->stsc_samples_per_chunk =
(int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t));
f->track[f->total_tracks - 1]->stsc_sample_desc_index =
(int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t));
for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count; i++)
{
f->track[f->total_tracks - 1]->stsc_first_chunk[i] = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->stsc_samples_per_chunk[i] = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->stsc_sample_desc_index[i] = mp4ff_read_int32(f);
}
return 0;
}
static int32_t mp4ff_read_stco(mp4ff_t *f)
{
int32_t i;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->stco_chunk_offset =
(int32_t*)malloc(f->track[f->total_tracks - 1]->stco_entry_count*sizeof(int32_t));
for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count; i++)
{
f->track[f->total_tracks - 1]->stco_chunk_offset[i] = mp4ff_read_int32(f);
}
return 0;
}
static int32_t mp4ff_read_ctts(mp4ff_t *f)
{
int32_t i;
mp4ff_track_t * p_track = f->track[f->total_tracks - 1];
if (p_track->ctts_entry_count) return 0;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
p_track->ctts_entry_count = mp4ff_read_int32(f);
p_track->ctts_sample_count = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t));
p_track->ctts_sample_offset = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t));
if (p_track->ctts_sample_count == 0 || p_track->ctts_sample_offset == 0)
{
if (p_track->ctts_sample_count) {free(p_track->ctts_sample_count);p_track->ctts_sample_count=0;}
if (p_track->ctts_sample_offset) {free(p_track->ctts_sample_offset);p_track->ctts_sample_offset=0;}
p_track->ctts_entry_count = 0;
return 0;
}
else
{
for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count; i++)
{
p_track->ctts_sample_count[i] = mp4ff_read_int32(f);
p_track->ctts_sample_offset[i] = mp4ff_read_int32(f);
}
return 1;
}
}
static int32_t mp4ff_read_stts(mp4ff_t *f)
{
int32_t i;
mp4ff_track_t * p_track = f->track[f->total_tracks - 1];
if (p_track->stts_entry_count) return 0;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
p_track->stts_entry_count = mp4ff_read_int32(f);
p_track->stts_sample_count = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t));
p_track->stts_sample_delta = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t));
if (p_track->stts_sample_count == 0 || p_track->stts_sample_delta == 0)
{
if (p_track->stts_sample_count) {free(p_track->stts_sample_count);p_track->stts_sample_count=0;}
if (p_track->stts_sample_delta) {free(p_track->stts_sample_delta);p_track->stts_sample_delta=0;}
p_track->stts_entry_count = 0;
return 0;
}
else
{
for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count; i++)
{
p_track->stts_sample_count[i] = mp4ff_read_int32(f);
p_track->stts_sample_delta[i] = mp4ff_read_int32(f);
}
return 1;
}
}
static int32_t mp4ff_read_mvhd(mp4ff_t *f)
{
int32_t i;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
/* creation_time */ mp4ff_read_int32(f);
/* modification_time */ mp4ff_read_int32(f);
f->time_scale = mp4ff_read_int32(f);
f->duration = mp4ff_read_int32(f);
/* preferred_rate */ mp4ff_read_int32(f); /*mp4ff_read_fixed32(f);*/
/* preferred_volume */ mp4ff_read_int16(f); /*mp4ff_read_fixed16(f);*/
for (i = 0; i < 10; i++)
{
/* reserved */ mp4ff_read_char(f);
}
for (i = 0; i < 9; i++)
{
mp4ff_read_int32(f); /* matrix */
}
/* preview_time */ mp4ff_read_int32(f);
/* preview_duration */ mp4ff_read_int32(f);
/* poster_time */ mp4ff_read_int32(f);
/* selection_time */ mp4ff_read_int32(f);
/* selection_duration */ mp4ff_read_int32(f);
/* current_time */ mp4ff_read_int32(f);
/* next_track_id */ mp4ff_read_int32(f);
return 0;
}
#if 0
static int32_t mp4ff_read_tkhd(mp4ff_t *f)
{
uint8_t version;
uint32_t flags;
version = mp4ff_read_char(f); /* version */
flags = mp4ff_read_int24(f); /* flags */
if (version==1)
{
mp4ff_read_int64(f);//creation-time
mp4ff_read_int64(f);//modification-time
mp4ff_read_int32(f);//track-id
mp4ff_read_int32(f);//reserved
f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration
}
else //version == 0
{
mp4ff_read_int32(f);//creation-time
mp4ff_read_int32(f);//modification-time
mp4ff_read_int32(f);//track-id
mp4ff_read_int32(f);//reserved
f->track[f->total_tracks - 1]->duration = mp4ff_read_int32(f);//duration
if (f->track[f->total_tracks - 1]->duration == 0xFFFFFFFF)
f->track[f->total_tracks - 1]->duration = 0xFFFFFFFFFFFFFFFF;
}
mp4ff_read_int32(f);//reserved
mp4ff_read_int32(f);//reserved
mp4ff_read_int16(f);//layer
mp4ff_read_int16(f);//pre-defined
mp4ff_read_int16(f);//volume
mp4ff_read_int16(f);//reserved
//matrix
mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f);
mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f);
mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f);
mp4ff_read_int32(f);//width
mp4ff_read_int32(f);//height
return 1;
}
#endif
static int32_t mp4ff_read_mdhd(mp4ff_t *f)
{
uint32_t version;
version = mp4ff_read_int32(f);
if (version==1)
{
mp4ff_read_int64(f);//creation-time
mp4ff_read_int64(f);//modification-time
f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale
f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration
}
else //version == 0
{
uint32_t temp;
mp4ff_read_int32(f);//creation-time
mp4ff_read_int32(f);//modification-time
f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale
temp = mp4ff_read_int32(f);
f->track[f->total_tracks - 1]->duration = (temp == (uint32_t)(-1)) ? (uint64_t)(-1) : (uint64_t)(temp);
}
mp4ff_read_int16(f);
mp4ff_read_int16(f);
return 1;
}
#ifdef USE_TAGGING
static int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size)
{
uint64_t subsize, sumsize = 0;
uint8_t atom_type;
uint8_t header_size = 0;
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
while (sumsize < (size-(header_size+4)))
{
subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
if (subsize <= header_size+4)
return 1;
if (atom_type == ATOM_ILST)
{
mp4ff_parse_metadata(f, (uint32_t)(subsize-(header_size+4)));
} else {
mp4ff_set_position(f, mp4ff_position(f)+subsize-header_size);
}
sumsize += subsize;
}
return 0;
}
#endif
int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type)
{
uint64_t dest_position = mp4ff_position(f)+size-8;
if (atom_type == ATOM_STSZ)
{
/* sample size box */
mp4ff_read_stsz(f);
} else if (atom_type == ATOM_STTS) {
/* time to sample box */
mp4ff_read_stts(f);
} else if (atom_type == ATOM_CTTS) {
/* composition offset box */
mp4ff_read_ctts(f);
} else if (atom_type == ATOM_STSC) {
/* sample to chunk box */
mp4ff_read_stsc(f);
} else if (atom_type == ATOM_STCO) {
/* chunk offset box */
mp4ff_read_stco(f);
} else if (atom_type == ATOM_STSD) {
/* sample description box */
mp4ff_read_stsd(f);
} else if (atom_type == ATOM_MVHD) {
/* movie header box */
mp4ff_read_mvhd(f);
} else if (atom_type == ATOM_MDHD) {
/* track header */
mp4ff_read_mdhd(f);
#ifdef ITUNES_DRM
} else if (atom_type == ATOM_FRMA) {
/* DRM track format */
mp4ff_read_frma(f);
} else if (atom_type == ATOM_IVIV) {
mp4ff_read_iviv(f, size-8);
} else if (atom_type == ATOM_NAME) {
mp4ff_read_name(f, size-8);
} else if (atom_type == ATOM_PRIV) {
mp4ff_read_priv(f, size-8);
} else if (atom_type == ATOM_USER) {
mp4ff_read_user(f, size-8);
} else if (atom_type == ATOM_KEY) {
mp4ff_read_key(f, size-8);
#endif
#ifdef USE_TAGGING
} else if (atom_type == ATOM_META) {
/* iTunes Metadata box */
mp4ff_read_meta(f, size);
#endif
}
mp4ff_set_position(f, dest_position);
return 0;
}

View file

@ -0,0 +1,474 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#include <stdlib.h>
#include <string.h>
#include "mp4ffint.h"
#include "drms.h"
mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f)
{
mp4ff_t *ff = malloc(sizeof(mp4ff_t));
memset(ff, 0, sizeof(mp4ff_t));
ff->stream = f;
parse_atoms(ff,0);
return ff;
}
mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t *f)
{
mp4ff_t *ff = malloc(sizeof(mp4ff_t));
memset(ff, 0, sizeof(mp4ff_t));
ff->stream = f;
parse_atoms(ff,1);
return ff;
}
void mp4ff_close(mp4ff_t *ff)
{
int32_t i;
for (i = 0; i < ff->total_tracks; i++)
{
if (ff->track[i])
{
if (ff->track[i]->stsz_table)
free(ff->track[i]->stsz_table);
if (ff->track[i]->stts_sample_count)
free(ff->track[i]->stts_sample_count);
if (ff->track[i]->stts_sample_delta)
free(ff->track[i]->stts_sample_delta);
if (ff->track[i]->stsc_first_chunk)
free(ff->track[i]->stsc_first_chunk);
if (ff->track[i]->stsc_samples_per_chunk)
free(ff->track[i]->stsc_samples_per_chunk);
if (ff->track[i]->stsc_sample_desc_index)
free(ff->track[i]->stsc_sample_desc_index);
if (ff->track[i]->stco_chunk_offset)
free(ff->track[i]->stco_chunk_offset);
if (ff->track[i]->decoderConfig)
free(ff->track[i]->decoderConfig);
if (ff->track[i]->ctts_sample_count)
free(ff->track[i]->ctts_sample_count);
if (ff->track[i]->ctts_sample_offset)
free(ff->track[i]->ctts_sample_offset);
#ifdef ITUNES_DRM
if (ff->track[i]->p_drms)
drms_free(ff->track[i]->p_drms);
#endif
free(ff->track[i]);
}
}
#ifdef USE_TAGGING
mp4ff_tag_delete(&(ff->tags));
#endif
if (ff) free(ff);
}
static void mp4ff_track_add(mp4ff_t *f)
{
f->total_tracks++;
f->track[f->total_tracks - 1] = malloc(sizeof(mp4ff_track_t));
memset(f->track[f->total_tracks - 1], 0, sizeof(mp4ff_track_t));
}
static int need_parse_when_meta_only(uint8_t atom_type)
{
switch(atom_type)
{
case ATOM_EDTS:
// case ATOM_MDIA:
// case ATOM_MINF:
case ATOM_DRMS:
case ATOM_SINF:
case ATOM_SCHI:
// case ATOM_STBL:
// case ATOM_STSD:
case ATOM_STTS:
case ATOM_STSZ:
case ATOM_STZ2:
case ATOM_STCO:
case ATOM_STSC:
// case ATOM_CTTS:
case ATOM_FRMA:
case ATOM_IVIV:
case ATOM_PRIV:
return 0;
default:
return 1;
}
}
/* parse atoms that are sub atoms of other atoms */
int32_t parse_sub_atoms(mp4ff_t *f, const uint64_t total_size,int meta_only)
{
uint64_t size;
uint8_t atom_type = 0;
uint64_t counted_size = 0;
uint8_t header_size = 0;
while (counted_size < total_size)
{
size = mp4ff_atom_read_header(f, &atom_type, &header_size);
counted_size += size;
/* check for end of file */
if (size == 0)
break;
/* we're starting to read a new track, update index,
* so that all data and tables get written in the right place
*/
if (atom_type == ATOM_TRAK)
{
mp4ff_track_add(f);
}
/* parse subatoms */
if (meta_only && !need_parse_when_meta_only(atom_type))
{
mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
} else if (atom_type < SUBATOMIC)
{
parse_sub_atoms(f, size-header_size,meta_only);
} else {
mp4ff_atom_read(f, (uint32_t)size, atom_type);
}
}
return 0;
}
/* parse root atoms */
int32_t parse_atoms(mp4ff_t *f,int meta_only)
{
uint64_t size;
uint8_t atom_type = 0;
uint8_t header_size = 0;
f->file_size = 0;
while ((size = mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0)
{
f->file_size += size;
f->last_atom = atom_type;
if (atom_type == ATOM_MDAT && f->moov_read)
{
/* moov atom is before mdat, we can stop reading when mdat is encountered */
/* file position will stay at beginning of mdat data */
// break;
}
if (atom_type == ATOM_MOOV && size > header_size)
{
f->moov_read = 1;
f->moov_offset = mp4ff_position(f)-header_size;
f->moov_size = size;
}
/* parse subatoms */
if (meta_only && !need_parse_when_meta_only(atom_type))
{
mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
} else if (atom_type < SUBATOMIC)
{
parse_sub_atoms(f, size-header_size,meta_only);
} else {
/* skip this atom */
mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
}
}
return 0;
}
int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int32_t track,
uint8_t** ppBuf, uint32_t* pBufSize)
{
if (track >= f->total_tracks)
{
*ppBuf = NULL;
*pBufSize = 0;
return 1;
}
if (f->track[track]->decoderConfig == NULL || f->track[track]->decoderConfigLen == 0)
{
*ppBuf = NULL;
*pBufSize = 0;
} else {
*ppBuf = malloc(f->track[track]->decoderConfigLen);
if (*ppBuf == NULL)
{
*pBufSize = 0;
return 1;
}
memcpy(*ppBuf, f->track[track]->decoderConfig, f->track[track]->decoderConfigLen);
*pBufSize = f->track[track]->decoderConfigLen;
}
return 0;
}
int32_t mp4ff_get_track_type(const mp4ff_t *f, const int track)
{
return f->track[track]->type;
}
int32_t mp4ff_total_tracks(const mp4ff_t *f)
{
return f->total_tracks;
}
int32_t mp4ff_time_scale(const mp4ff_t *f, const int32_t track)
{
return f->track[track]->timeScale;
}
uint32_t mp4ff_get_avg_bitrate(const mp4ff_t *f, const int32_t track)
{
return f->track[track]->avgBitrate;
}
uint32_t mp4ff_get_max_bitrate(const mp4ff_t *f, const int32_t track)
{
return f->track[track]->maxBitrate;
}
int64_t mp4ff_get_track_duration(const mp4ff_t *f, const int32_t track)
{
return f->track[track]->duration;
}
int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track)
{
int64_t duration = mp4ff_get_track_duration(f,track);
if (duration!=-1)
{
int64_t offset = mp4ff_get_sample_offset(f,track,0);
if (offset > duration) duration = 0;
else duration -= offset;
}
return duration;
}
int32_t mp4ff_num_samples(const mp4ff_t *f, const int32_t track)
{
int32_t i;
int32_t total = 0;
for (i = 0; i < f->track[track]->stts_entry_count; i++)
{
total += f->track[track]->stts_sample_count[i];
}
return total;
}
uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track)
{
return f->track[track]->sampleRate;
}
uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track)
{
return f->track[track]->channelCount;
}
uint32_t mp4ff_get_audio_type(const mp4ff_t * f,const int32_t track)
{
return f->track[track]->audioType;
}
int32_t mp4ff_get_sample_duration_use_offsets(const mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t d,o;
d = mp4ff_get_sample_duration(f,track,sample);
if (d!=-1)
{
o = mp4ff_get_sample_offset(f,track,sample);
if (o>d) d = 0;
else d -= o;
}
return d;
}
int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t i, co = 0;
for (i = 0; i < f->track[track]->stts_entry_count; i++)
{
int32_t delta = f->track[track]->stts_sample_count[i];
if (sample < co + delta)
return f->track[track]->stts_sample_delta[i];
co += delta;
}
return (int32_t)(-1);
}
int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t i, co = 0;
int64_t acc = 0;
for (i = 0; i < f->track[track]->stts_entry_count; i++)
{
int32_t delta = f->track[track]->stts_sample_count[i];
if (sample < co + delta)
{
acc += f->track[track]->stts_sample_delta[i] * (sample - co);
return acc;
}
else
{
acc += f->track[track]->stts_sample_delta[i] * delta;
}
co += delta;
}
return (int64_t)(-1);
}
int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t i, co = 0;
for (i = 0; i < f->track[track]->ctts_entry_count; i++)
{
int32_t delta = f->track[track]->ctts_sample_count[i];
if (sample < co + delta)
return f->track[track]->ctts_sample_offset[i];
co += delta;
}
return 0;
}
int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip)
{
int32_t i, co = 0;
int64_t offset_total = 0;
mp4ff_track_t * p_track = f->track[track];
for (i = 0; i < p_track->stts_entry_count; i++)
{
int32_t sample_count = p_track->stts_sample_count[i];
int32_t sample_delta = p_track->stts_sample_delta[i];
int64_t offset_delta = (int64_t)sample_delta * (int64_t)sample_count;
if (offset < offset_total + offset_delta)
{
int64_t offset_fromstts = offset - offset_total;
if (toskip) *toskip = (int32_t)(offset_fromstts % sample_delta);
return co + (int32_t)(offset_fromstts / sample_delta);
}
else
{
offset_total += offset_delta;
}
co += sample_count;
}
return (int32_t)(-1);
}
int32_t mp4ff_find_sample_use_offsets(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip)
{
return mp4ff_find_sample(f,track,offset + mp4ff_get_sample_offset(f,track,0),toskip);
}
int32_t mp4ff_read_sample(mp4ff_t *f, const int32_t track, const int32_t sample,
uint8_t **audio_buffer, uint32_t *bytes)
{
int32_t result = 0;
*bytes = mp4ff_audio_frame_size(f, track, sample);
if (*bytes==0) return 0;
*audio_buffer = (uint8_t*)malloc(*bytes);
mp4ff_set_sample_position(f, track, sample);
result = mp4ff_read_data(f, *audio_buffer, *bytes);
if (!result)
{
free(*audio_buffer);
*audio_buffer = 0;
return 0;
}
#ifdef ITUNES_DRM
if (f->track[track]->p_drms != NULL)
{
drms_decrypt(f->track[track]->p_drms, (uint32_t*)*audio_buffer, *bytes);
}
#endif
return *bytes;
}
int32_t mp4ff_read_sample_v2(mp4ff_t *f, const int track, const int sample,unsigned char *buffer)
{
int32_t result = 0;
int32_t size = mp4ff_audio_frame_size(f,track,sample);
if (size<=0) return 0;
mp4ff_set_sample_position(f, track, sample);
result = mp4ff_read_data(f,buffer,size);
#ifdef ITUNES_DRM
if (f->track[track]->p_drms != NULL)
{
drms_decrypt(f->track[track]->p_drms, (uint32_t*)buffer, size);
}
#endif
return result;
}
int32_t mp4ff_read_sample_getsize(mp4ff_t *f, const int track, const int sample)
{
int32_t temp = mp4ff_audio_frame_size(f, track, sample);
if (temp<0) temp = 0;
return temp;
}

View file

@ -0,0 +1,131 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifndef MP4FF_H
#define MP4FF_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "mp4ff_int_types.h"
/* file callback structure */
typedef struct
{
uint32_t (*read)(void *user_data, void *buffer, uint32_t length);
uint32_t (*write)(void *udata, void *buffer, uint32_t length);
uint32_t (*seek)(void *user_data, uint64_t position);
uint32_t (*truncate)(void *user_data);
void *user_data;
} mp4ff_callback_t;
/* mp4 main file structure */
typedef void* mp4ff_t;
/* API */
mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f);
mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t *f);
void mp4ff_close(mp4ff_t *f);
int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_get_sample_duration_use_offsets(const mp4ff_t *f, const int32_t track, const int32_t sample);
int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip);
int32_t mp4ff_find_sample_use_offsets(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip);
int32_t mp4ff_read_sample(mp4ff_t *f, const int track, const int sample,
unsigned char **audio_buffer, unsigned int *bytes);
int32_t mp4ff_read_sample_v2(mp4ff_t *f, const int track, const int sample,unsigned char *buffer);//returns 0 on error, number of bytes read on success, use mp4ff_read_sample_getsize() to check buffer size needed
int32_t mp4ff_read_sample_getsize(mp4ff_t *f, const int track, const int sample);//returns 0 on error, buffer size needed for mp4ff_read_sample_v2() on success
int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int track,
unsigned char** ppBuf, unsigned int* pBufSize);
int32_t mp4ff_get_track_type(const mp4ff_t *f, const int track);
int32_t mp4ff_total_tracks(const mp4ff_t *f);
int32_t mp4ff_num_samples(const mp4ff_t *f, const int track);
int32_t mp4ff_time_scale(const mp4ff_t *f, const int track);
uint32_t mp4ff_get_avg_bitrate(const mp4ff_t *f, const int32_t track);
uint32_t mp4ff_get_max_bitrate(const mp4ff_t *f, const int32_t track);
int64_t mp4ff_get_track_duration(const mp4ff_t *f, const int32_t track); //returns (-1) if unknown
int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track); //returns (-1) if unknown
uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track);
uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track);
uint32_t mp4ff_get_audio_type(const mp4ff_t * f,const int32_t track);
/* metadata */
int mp4ff_meta_get_num_items(const mp4ff_t *f);
int mp4ff_meta_get_by_index(const mp4ff_t *f, unsigned int index,
char **item, char **value);
int mp4ff_meta_get_title(const mp4ff_t *f, char **value);
int mp4ff_meta_get_artist(const mp4ff_t *f, char **value);
int mp4ff_meta_get_writer(const mp4ff_t *f, char **value);
int mp4ff_meta_get_album(const mp4ff_t *f, char **value);
int mp4ff_meta_get_date(const mp4ff_t *f, char **value);
int mp4ff_meta_get_tool(const mp4ff_t *f, char **value);
int mp4ff_meta_get_comment(const mp4ff_t *f, char **value);
int mp4ff_meta_get_genre(const mp4ff_t *f, char **value);
int mp4ff_meta_get_track(const mp4ff_t *f, char **value);
int mp4ff_meta_get_disc(const mp4ff_t *f, char **value);
int mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value);
int mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value);
int mp4ff_meta_get_compilation(const mp4ff_t *f, char **value);
int mp4ff_meta_get_tempo(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value);
#ifdef USE_TAGGING
/* metadata tag structure */
typedef struct
{
char *item;
char *value;
} mp4ff_tag_t;
/* metadata list structure */
typedef struct
{
mp4ff_tag_t *tags;
uint32_t count;
} mp4ff_metadata_t;
int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View file

@ -0,0 +1,23 @@
#ifndef _MP4FF_INT_TYPES_H_
#define _MP4FF_INT_TYPES_H_
#ifdef _WIN32
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#endif

View file

@ -0,0 +1,373 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifndef MP4FF_INTERNAL_H
#define MP4FF_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "mp4ff_int_types.h"
#if defined(_WIN32) && !defined(_WIN32_WCE)
#define ITUNES_DRM
static __inline uint32_t GetDWLE( void const * _p )
{
uint8_t * p = (uint8_t *)_p;
return ( ((uint32_t)p[3] << 24) | ((uint32_t)p[2] << 16)
| ((uint32_t)p[1] << 8) | p[0] );
}
static __inline uint32_t U32_AT( void const * _p )
{
uint8_t * p = (uint8_t *)_p;
return ( ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16)
| ((uint32_t)p[2] << 8) | p[3] );
}
static __inline uint64_t U64_AT( void const * _p )
{
uint8_t * p = (uint8_t *)_p;
return ( ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48)
| ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32)
| ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16)
| ((uint64_t)p[6] << 8) | p[7] );
}
#ifdef WORDS_BIGENDIAN
# define VLC_FOURCC( a, b, c, d ) \
( ((uint32_t)d) | ( ((uint32_t)c) << 8 ) \
| ( ((uint32_t)b) << 16 ) | ( ((uint32_t)a) << 24 ) )
# define VLC_TWOCC( a, b ) \
( (uint16_t)(b) | ( (uint16_t)(a) << 8 ) )
#else
# define VLC_FOURCC( a, b, c, d ) \
( ((uint32_t)a) | ( ((uint32_t)b) << 8 ) \
| ( ((uint32_t)c) << 16 ) | ( ((uint32_t)d) << 24 ) )
# define VLC_TWOCC( a, b ) \
( (uint16_t)(a) | ( (uint16_t)(b) << 8 ) )
#endif
#define FOURCC_user VLC_FOURCC( 'u', 's', 'e', 'r' )
#define FOURCC_key VLC_FOURCC( 'k', 'e', 'y', ' ' )
#define FOURCC_iviv VLC_FOURCC( 'i', 'v', 'i', 'v' )
#define FOURCC_name VLC_FOURCC( 'n', 'a', 'm', 'e' )
#define FOURCC_priv VLC_FOURCC( 'p', 'r', 'i', 'v' )
#endif
#define MAX_TRACKS 1024
#define TRACK_UNKNOWN 0
#define TRACK_AUDIO 1
#define TRACK_VIDEO 2
#define TRACK_SYSTEM 3
#define SUBATOMIC 128
/* atoms without subatoms */
#define ATOM_FTYP 129
#define ATOM_MDAT 130
#define ATOM_MVHD 131
#define ATOM_TKHD 132
#define ATOM_TREF 133
#define ATOM_MDHD 134
#define ATOM_VMHD 135
#define ATOM_SMHD 136
#define ATOM_HMHD 137
#define ATOM_STSD 138
#define ATOM_STTS 139
#define ATOM_STSZ 140
#define ATOM_STZ2 141
#define ATOM_STCO 142
#define ATOM_STSC 143
#define ATOM_MP4A 144
#define ATOM_MP4V 145
#define ATOM_MP4S 146
#define ATOM_ESDS 147
#define ATOM_META 148 /* iTunes Metadata box */
#define ATOM_NAME 149 /* iTunes Metadata name box */
#define ATOM_DATA 150 /* iTunes Metadata data box */
#define ATOM_CTTS 151
#define ATOM_FRMA 152
#define ATOM_IVIV 153
#define ATOM_PRIV 154
#define ATOM_USER 155
#define ATOM_KEY 156
#define ATOM_UNKNOWN 255
#define ATOM_FREE ATOM_UNKNOWN
#define ATOM_SKIP ATOM_UNKNOWN
/* atoms with subatoms */
#define ATOM_MOOV 1
#define ATOM_TRAK 2
#define ATOM_EDTS 3
#define ATOM_MDIA 4
#define ATOM_MINF 5
#define ATOM_STBL 6
#define ATOM_UDTA 7
#define ATOM_ILST 8 /* iTunes Metadata list */
#define ATOM_TITLE 9
#define ATOM_ARTIST 10
#define ATOM_WRITER 11
#define ATOM_ALBUM 12
#define ATOM_DATE 13
#define ATOM_TOOL 14
#define ATOM_COMMENT 15
#define ATOM_GENRE1 16
#define ATOM_TRACK 17
#define ATOM_DISC 18
#define ATOM_COMPILATION 19
#define ATOM_GENRE2 20
#define ATOM_TEMPO 21
#define ATOM_COVER 22
#define ATOM_DRMS 23
#define ATOM_SINF 24
#define ATOM_SCHI 25
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
#if !(defined(_WIN32) || defined(_WIN32_WCE))
#define stricmp strcasecmp
#endif
/* file callback structure */
typedef struct
{
uint32_t (*read)(void *user_data, void *buffer, uint32_t length);
uint32_t (*write)(void *udata, void *buffer, uint32_t length);
uint32_t (*seek)(void *user_data, uint64_t position);
uint32_t (*truncate)(void *user_data);
void *user_data;
} mp4ff_callback_t;
/* metadata tag structure */
typedef struct
{
char *item;
char *value;
} mp4ff_tag_t;
/* metadata list structure */
typedef struct
{
mp4ff_tag_t *tags;
uint32_t count;
} mp4ff_metadata_t;
typedef struct
{
int32_t type;
int32_t channelCount;
int32_t sampleSize;
uint16_t sampleRate;
int32_t audioType;
/* stsd */
int32_t stsd_entry_count;
/* stsz */
int32_t stsz_sample_size;
int32_t stsz_sample_count;
int32_t *stsz_table;
/* stts */
int32_t stts_entry_count;
int32_t *stts_sample_count;
int32_t *stts_sample_delta;
/* stsc */
int32_t stsc_entry_count;
int32_t *stsc_first_chunk;
int32_t *stsc_samples_per_chunk;
int32_t *stsc_sample_desc_index;
/* stsc */
int32_t stco_entry_count;
int32_t *stco_chunk_offset;
/* ctts */
int32_t ctts_entry_count;
int32_t *ctts_sample_count;
int32_t *ctts_sample_offset;
/* esde */
uint8_t *decoderConfig;
int32_t decoderConfigLen;
uint32_t maxBitrate;
uint32_t avgBitrate;
uint32_t timeScale;
uint64_t duration;
#ifdef ITUNES_DRM
/* drms */
void *p_drms;
#endif
} mp4ff_track_t;
/* mp4 main file structure */
typedef struct
{
/* stream to read from */
mp4ff_callback_t *stream;
int64_t current_position;
int32_t moov_read;
uint64_t moov_offset;
uint64_t moov_size;
uint8_t last_atom;
uint64_t file_size;
/* mvhd */
int32_t time_scale;
int32_t duration;
/* incremental track index while reading the file */
int32_t total_tracks;
/* track data */
mp4ff_track_t *track[MAX_TRACKS];
/* metadata */
mp4ff_metadata_t tags;
} mp4ff_t;
/* mp4util.c */
int32_t mp4ff_read_data(mp4ff_t *f, int8_t *data, uint32_t size);
int32_t mp4ff_write_data(mp4ff_t *f, int8_t *data, uint32_t size);
uint64_t mp4ff_read_int64(mp4ff_t *f);
uint32_t mp4ff_read_int32(mp4ff_t *f);
uint32_t mp4ff_read_int24(mp4ff_t *f);
uint16_t mp4ff_read_int16(mp4ff_t *f);
uint8_t mp4ff_read_char(mp4ff_t *f);
int32_t mp4ff_write_int32(mp4ff_t *f,const uint32_t data);
uint32_t mp4ff_read_mp4_descr_length(mp4ff_t *f);
int64_t mp4ff_position(const mp4ff_t *f);
int32_t mp4ff_set_position(mp4ff_t *f, const int64_t position);
int32_t mp4ff_truncate(mp4ff_t * f);
char * mp4ff_read_string(mp4ff_t * f,uint32_t length);
/* mp4atom.c */
static int32_t mp4ff_atom_get_size(const int8_t *data);
static int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1, const int8_t c1, const int8_t d1,
const int8_t a2, const int8_t b2, const int8_t c2, const int8_t d2);
static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b, const int8_t c, const int8_t d);
uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size);
static int32_t mp4ff_read_stsz(mp4ff_t *f);
static int32_t mp4ff_read_esds(mp4ff_t *f);
static int32_t mp4ff_read_mp4a(mp4ff_t *f);
static int32_t mp4ff_read_stsd(mp4ff_t *f);
static int32_t mp4ff_read_stsc(mp4ff_t *f);
static int32_t mp4ff_read_stco(mp4ff_t *f);
static int32_t mp4ff_read_stts(mp4ff_t *f);
#ifdef USE_TAGGING
static int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size);
#endif
int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type);
/* mp4sample.c */
static int32_t mp4ff_chunk_of_sample(const mp4ff_t *f, const int32_t track, const int32_t sample,
int32_t *chunk_sample, int32_t *chunk);
static int32_t mp4ff_chunk_to_offset(const mp4ff_t *f, const int32_t track, const int32_t chunk);
static int32_t mp4ff_sample_range_size(const mp4ff_t *f, const int32_t track,
const int32_t chunk_sample, const int32_t sample);
static int32_t mp4ff_sample_to_offset(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_audio_frame_size(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_set_sample_position(mp4ff_t *f, const int32_t track, const int32_t sample);
#ifdef USE_TAGGING
/* mp4meta.c */
static int32_t mp4ff_tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value);
static int32_t mp4ff_tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value);
static int32_t mp4ff_set_metadata_name(mp4ff_t *f, const uint8_t atom_type, char **name);
static int32_t mp4ff_parse_tag(mp4ff_t *f, const uint8_t parent_atom_type, const int32_t size);
static int32_t mp4ff_meta_find_by_name(const mp4ff_t *f, const char *item, char **value);
int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size);
int32_t mp4ff_tag_delete(mp4ff_metadata_t *tags);
int32_t mp4ff_meta_get_num_items(const mp4ff_t *f);
int32_t mp4ff_meta_get_by_index(const mp4ff_t *f, uint32_t index,
char **item, char **value);
int32_t mp4ff_meta_get_title(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_artist(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_writer(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_album(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_date(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_tool(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_comment(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_genre(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_tempo(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value);
#endif
/* mp4ff.c */
mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f);
#ifdef USE_TAGGING
mp4ff_t *mp4ff_open_edit(mp4ff_callback_t *f);
#endif
void mp4ff_close(mp4ff_t *ff);
void mp4ff_track_add(mp4ff_t *f);
int32_t parse_sub_atoms(mp4ff_t *f, const uint64_t total_size,int meta_only);
int32_t parse_atoms(mp4ff_t *f,int meta_only);
int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample);
int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample);
int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip);
int32_t mp4ff_read_sample(mp4ff_t *f, const int32_t track, const int32_t sample,
uint8_t **audio_buffer, uint32_t *bytes);
int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int32_t track,
uint8_t** ppBuf, uint32_t* pBufSize);
int32_t mp4ff_total_tracks(const mp4ff_t *f);
int32_t mp4ff_time_scale(const mp4ff_t *f, const int32_t track);
int32_t mp4ff_num_samples(const mp4ff_t *f, const int32_t track);
uint32_t mp4ff_meta_genre_to_index(const char * genrestr);//returns 1-based index, 0 if not found
const char * mp4ff_meta_index_to_genre(uint32_t idx);//returns pointer to static string
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View file

@ -0,0 +1,426 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#ifdef USE_TAGGING
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mp4ffint.h"
static int32_t mp4ff_tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value)
{
void *backup = (void *)tags->tags;
if (!item || (item && !*item) || !value) return 0;
tags->tags = (mp4ff_tag_t*)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t));
if (!tags->tags)
{
if (backup) free(backup);
return 0;
} else {
tags->tags[tags->count].item = strdup(item);
tags->tags[tags->count].value = strdup(value);
if (!tags->tags[tags->count].item || !tags->tags[tags->count].value)
{
if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item);
if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value);
tags->tags[tags->count].item = NULL;
tags->tags[tags->count].value = NULL;
return 0;
}
tags->count++;
return 1;
}
}
static int32_t mp4ff_tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value)
{
unsigned int i;
if (!item || (item && !*item) || !value) return 0;
for (i = 0; i < tags->count; i++)
{
if (!stricmp(tags->tags[i].item, item))
{
free(tags->tags[i].value);
tags->tags[i].value = strdup(value);
return 1;
}
}
return mp4ff_tag_add_field(tags, item, value);
}
int32_t mp4ff_tag_delete(mp4ff_metadata_t *tags)
{
uint32_t i;
for (i = 0; i < tags->count; i++)
{
if (tags->tags[i].item) free(tags->tags[i].item);
if (tags->tags[i].value) free(tags->tags[i].value);
}
if (tags->tags) free(tags->tags);
tags->tags = NULL;
tags->count = 0;
return 0;
}
static const char* ID3v1GenreList[] = {
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
"Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
"Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
"Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
"Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
"Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
"Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
"Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
"Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
"Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
"Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
"New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
"Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
"Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
"Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
"Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
"Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
"Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
"Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
"Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
"Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
"Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
"Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
"Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
"Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
"SynthPop",
};
uint32_t mp4ff_meta_genre_to_index(const char * genrestr)
{
unsigned n;
for(n=0;n<sizeof(ID3v1GenreList)/sizeof(ID3v1GenreList[0]);n++)
{
if (!stricmp(genrestr,ID3v1GenreList[n])) return n+1;
}
return 0;
}
const char * mp4ff_meta_index_to_genre(uint32_t idx)
{
if (idx>0 && idx<=sizeof(ID3v1GenreList)/sizeof(ID3v1GenreList[0]))
{
return ID3v1GenreList[idx-1];
}
else
{
return 0;
}
}
static int32_t TrackToString(char** str, const uint16_t track, const uint16_t totalTracks)
{
char temp[32];
sprintf(temp, "%.5u of %.5u", track, totalTracks);
*str = strdup(temp);
return 0;
}
static int32_t mp4ff_set_metadata_name(mp4ff_t *f, const uint8_t atom_type, char **name)
{
static char *tag_names[] = {
"unknown", "title", "artist", "writer", "album",
"date", "tool", "comment", "genre", "track",
"disc", "compilation", "genre", "tempo", "cover"
};
uint8_t tag_idx = 0;
switch (atom_type)
{
case ATOM_TITLE: tag_idx = 1; break;
case ATOM_ARTIST: tag_idx = 2; break;
case ATOM_WRITER: tag_idx = 3; break;
case ATOM_ALBUM: tag_idx = 4; break;
case ATOM_DATE: tag_idx = 5; break;
case ATOM_TOOL: tag_idx = 6; break;
case ATOM_COMMENT: tag_idx = 7; break;
case ATOM_GENRE1: tag_idx = 8; break;
case ATOM_TRACK: tag_idx = 9; break;
case ATOM_DISC: tag_idx = 10; break;
case ATOM_COMPILATION: tag_idx = 11; break;
case ATOM_GENRE2: tag_idx = 12; break;
case ATOM_TEMPO: tag_idx = 13; break;
case ATOM_COVER: tag_idx = 14; break;
default: tag_idx = 0; break;
}
*name = strdup(tag_names[tag_idx]);
return 0;
}
static int32_t mp4ff_parse_tag(mp4ff_t *f, const uint8_t parent_atom_type, const int32_t size)
{
uint8_t atom_type;
uint8_t header_size = 0;
uint64_t subsize, sumsize = 0;
char * name = NULL;
char * data = NULL;
uint32_t done = 0;
while (sumsize < size)
{
uint64_t destpos;
subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
destpos = mp4ff_position(f)+subsize-header_size;
if (!done)
{
if (atom_type == ATOM_DATA)
{
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
mp4ff_read_int32(f); /* reserved */
/* some need special attention */
if (parent_atom_type == ATOM_GENRE2 || parent_atom_type == ATOM_TEMPO)
{
if (subsize - header_size >= 8 + 2)
{
uint16_t val = mp4ff_read_int16(f);
if (parent_atom_type == ATOM_TEMPO)
{
char temp[16];
sprintf(temp, "%.5u BPM", val);
mp4ff_tag_add_field(&(f->tags), "tempo", temp);
}
else
{
const char * temp = mp4ff_meta_index_to_genre(val);
if (temp)
{
mp4ff_tag_add_field(&(f->tags), "genre", temp);
}
}
done = 1;
}
} else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) {
if (!done && subsize - header_size >= 8 + 8)
{
uint16_t index,total;
char temp[32];
mp4ff_read_int16(f);
index = mp4ff_read_int16(f);
total = mp4ff_read_int16(f);
mp4ff_read_int16(f);
sprintf(temp,"%d",index);
mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "track" : "disc", temp);
if (total>0)
{
sprintf(temp,"%d",total);
mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "totaltracks" : "totaldiscs", temp);
}
done = 1;
}
} else
{
if (data) {free(data);data = NULL;}
data = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+8)));
}
} else if (atom_type == ATOM_NAME) {
if (!done)
{
mp4ff_read_char(f); /* version */
mp4ff_read_int24(f); /* flags */
if (name) free(name);
name = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+4)));
}
}
mp4ff_set_position(f, destpos);
sumsize += subsize;
}
}
if (data)
{
if (!done)
{
if (name == NULL) mp4ff_set_metadata_name(f, parent_atom_type, &name);
if (name) mp4ff_tag_add_field(&(f->tags), name, data);
}
free(data);
}
if (name) free(name);
return 1;
}
int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size)
{
uint64_t subsize, sumsize = 0;
uint8_t atom_type;
uint8_t header_size = 0;
while (sumsize < size)
{
subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
mp4ff_parse_tag(f, atom_type, (uint32_t)(subsize-header_size));
sumsize += subsize;
}
return 0;
}
/* find a metadata item by name */
/* returns 0 if item found, 1 if no such item */
static int32_t mp4ff_meta_find_by_name(const mp4ff_t *f, const char *item, char **value)
{
uint32_t i;
for (i = 0; i < f->tags.count; i++)
{
if (!stricmp(f->tags.tags[i].item, item))
{
*value = strdup(f->tags.tags[i].value);
return 1;
}
}
*value = NULL;
/* not found */
return 0;
}
int32_t mp4ff_meta_get_num_items(const mp4ff_t *f)
{
return f->tags.count;
}
int32_t mp4ff_meta_get_by_index(const mp4ff_t *f, uint32_t index,
char **item, char **value)
{
if (index >= f->tags.count)
{
*item = NULL;
*value = NULL;
return 0;
} else {
*item = strdup(f->tags.tags[index].item);
*value = strdup(f->tags.tags[index].value);
return 1;
}
}
int32_t mp4ff_meta_get_title(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "title", value);
}
int32_t mp4ff_meta_get_artist(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "artist", value);
}
int32_t mp4ff_meta_get_writer(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "writer", value);
}
int32_t mp4ff_meta_get_album(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "album", value);
}
int32_t mp4ff_meta_get_date(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "date", value);
}
int32_t mp4ff_meta_get_tool(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "tool", value);
}
int32_t mp4ff_meta_get_comment(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "comment", value);
}
int32_t mp4ff_meta_get_genre(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "genre", value);
}
int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "track", value);
}
int32_t mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "totaltracks", value);
}
int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "disc", value);
}
int32_t mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "totaldiscs", value);
}
int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "compilation", value);
}
int32_t mp4ff_meta_get_tempo(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "tempo", value);
}
int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value)
{
return mp4ff_meta_find_by_name(f, "cover", value);
}
#endif

View file

@ -0,0 +1,152 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#include <stdlib.h>
#include "mp4ffint.h"
static int32_t mp4ff_chunk_of_sample(const mp4ff_t *f, const int32_t track, const int32_t sample,
int32_t *chunk_sample, int32_t *chunk)
{
int32_t total_entries = 0;
int32_t chunk2entry;
int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
if (f->track[track] == NULL)
{
return -1;
}
total_entries = f->track[track]->stsc_entry_count;
chunk1 = 1;
chunk1samples = 0;
chunk2entry = 0;
do
{
chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
*chunk = chunk2 - chunk1;
range_samples = *chunk * chunk1samples;
if (sample < total + range_samples) break;
chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
chunk1 = chunk2;
if(chunk2entry < total_entries)
{
chunk2entry++;
total += range_samples;
}
} while (chunk2entry < total_entries);
if (chunk1samples)
*chunk = (sample - total) / chunk1samples + chunk1;
else
*chunk = 1;
*chunk_sample = total + (*chunk - chunk1) * chunk1samples;
return 0;
}
static int32_t mp4ff_chunk_to_offset(const mp4ff_t *f, const int32_t track, const int32_t chunk)
{
const mp4ff_track_t * p_track = f->track[track];
if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count))
{
return p_track->stco_chunk_offset[p_track->stco_entry_count - 1];
} else if (p_track->stco_entry_count) {
return p_track->stco_chunk_offset[chunk - 1];
} else {
return 8;
}
return 0;
}
static int32_t mp4ff_sample_range_size(const mp4ff_t *f, const int32_t track,
const int32_t chunk_sample, const int32_t sample)
{
int32_t i, total;
const mp4ff_track_t * p_track = f->track[track];
if (p_track->stsz_sample_size)
{
return (sample - chunk_sample) * p_track->stsz_sample_size;
}
else
{
if (sample>=p_track->stsz_sample_count) return 0;//error
for(i = chunk_sample, total = 0; i < sample; i++)
{
total += p_track->stsz_table[i];
}
}
return total;
}
static int32_t mp4ff_sample_to_offset(const mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk);
chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f, track, chunk_sample, sample);
return chunk_offset2;
}
int32_t mp4ff_audio_frame_size(const mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t bytes;
const mp4ff_track_t * p_track = f->track[track];
if (p_track->stsz_sample_size)
{
bytes = p_track->stsz_sample_size;
} else {
bytes = p_track->stsz_table[sample];
}
return bytes;
}
int32_t mp4ff_set_sample_position(mp4ff_t *f, const int32_t track, const int32_t sample)
{
int32_t offset;
offset = mp4ff_sample_to_offset(f, track, sample);
mp4ff_set_position(f, offset);
return 0;
}

View file

@ -0,0 +1,645 @@
#include <stdlib.h>
#include <string.h>
#include "mp4ffint.h"
#ifdef USE_TAGGING
static uint32_t fix_byte_order_32(uint32_t src)
{
uint32_t result;
uint32_t a, b, c, d;
int8_t data[4];
memcpy(data,&src,sizeof(src));
a = (uint8_t)data[0];
b = (uint8_t)data[1];
c = (uint8_t)data[2];
d = (uint8_t)data[3];
result = (a<<24) | (b<<16) | (c<<8) | d;
return (uint32_t)result;
}
static uint16_t fix_byte_order_16(uint16_t src)
{
uint16_t result;
uint16_t a, b;
int8_t data[2];
memcpy(data,&src,sizeof(src));
a = (uint8_t)data[0];
b = (uint8_t)data[1];
result = (a<<8) | b;
return (uint16_t)result;
}
typedef struct
{
void * data;
unsigned written;
unsigned allocated;
unsigned error;
} membuffer;
unsigned membuffer_write(membuffer * buf,const void * ptr,unsigned bytes)
{
unsigned dest_size = buf->written + bytes;
if (buf->error) return 0;
if (dest_size > buf->allocated)
{
do
{
buf->allocated <<= 1;
} while(dest_size > buf->allocated);
{
void * newptr = realloc(buf->data,buf->allocated);
if (newptr==0)
{
free(buf->data);
buf->data = 0;
buf->error = 1;
return 0;
}
buf->data = newptr;
}
}
if (ptr) memcpy((char*)buf->data + buf->written,ptr,bytes);
buf->written += bytes;
return bytes;
}
#define membuffer_write_data membuffer_write
unsigned membuffer_write_int32(membuffer * buf,uint32_t data)
{
uint8_t temp[4] = {(uint8_t)(data>>24),(uint8_t)(data>>16),(uint8_t)(data>>8),(uint8_t)data};
return membuffer_write_data(buf,temp,4);
}
unsigned membuffer_write_int24(membuffer * buf,uint32_t data)
{
uint8_t temp[3] = {(uint8_t)(data>>16),(uint8_t)(data>>8),(uint8_t)data};
return membuffer_write_data(buf,temp,3);
}
unsigned membuffer_write_int16(membuffer * buf,uint16_t data)
{
uint8_t temp[2] = {(uint8_t)(data>>8),(uint8_t)data};
return membuffer_write_data(buf,temp,2);
}
unsigned membuffer_write_atom_name(membuffer * buf,const char * data)
{
return membuffer_write_data(buf,data,4)==4 ? 1 : 0;
}
void membuffer_write_atom(membuffer * buf,const char * name,unsigned size,const void * data)
{
membuffer_write_int32(buf,size + 8);
membuffer_write_atom_name(buf,name);
membuffer_write_data(buf,data,size);
}
unsigned membuffer_write_string(membuffer * buf,const char * data)
{
return membuffer_write_data(buf,data,strlen(data));
}
unsigned membuffer_write_int8(membuffer * buf,uint8_t data)
{
return membuffer_write_data(buf,&data,1);
}
void * membuffer_get_ptr(const membuffer * buf)
{
return buf->data;
}
unsigned membuffer_get_size(const membuffer * buf)
{
return buf->written;
}
unsigned membuffer_error(const membuffer * buf)
{
return buf->error;
}
void membuffer_set_error(membuffer * buf) {buf->error = 1;}
unsigned membuffer_transfer_from_file(membuffer * buf,mp4ff_t * src,unsigned bytes)
{
unsigned oldsize;
void * bufptr;
oldsize = membuffer_get_size(buf);
if (membuffer_write_data(buf,0,bytes) != bytes) return 0;
bufptr = membuffer_get_ptr(buf);
if (bufptr==0) return 0;
if ((unsigned)mp4ff_read_data(src,(char*)bufptr + oldsize,bytes)!=bytes)
{
membuffer_set_error(buf);
return 0;
}
return bytes;
}
membuffer * membuffer_create()
{
const unsigned initial_size = 256;
membuffer * buf = (membuffer *) malloc(sizeof(membuffer));
buf->data = malloc(initial_size);
buf->written = 0;
buf->allocated = initial_size;
buf->error = buf->data == 0 ? 1 : 0;
return buf;
}
void membuffer_free(membuffer * buf)
{
if (buf->data) free(buf->data);
free(buf);
}
void * membuffer_detach(membuffer * buf)
{
void * ret;
if (buf->error) return 0;
ret = realloc(buf->data,buf->written);
if (ret == 0) free(buf->data);
buf->data = 0;
buf->error = 1;
return ret;
}
#if 0
/* metadata tag structure */
typedef struct
{
char *item;
char *value;
} mp4ff_tag_t;
/* metadata list structure */
typedef struct
{
mp4ff_tag_t *tags;
uint32_t count;
} mp4ff_metadata_t;
#endif
typedef struct
{
const char * atom;
const char * name;
} stdmeta_entry;
static stdmeta_entry stdmetas[] =
{
{"©nam","title"},
{"©ART","artist"},
{"©wrt","writer"},
{"©alb","album"},
{"©day","date"},
{"©too","tool"},
{"©cmt","comment"},
// {"©gen","genre"},
{"cpil","compilation"},
// {"trkn","track"},
// {"disk","disc"},
// {"gnre","genre"},
{"covr","cover"},
};
static const char* find_standard_meta(const char * name) //returns atom name if found, 0 if not
{
unsigned n;
for(n=0;n<sizeof(stdmetas)/sizeof(stdmetas[0]);n++)
{
if (!stricmp(name,stdmetas[n].name)) return stdmetas[n].atom;
}
return 0;
}
static void membuffer_write_track_tag(membuffer * buf,const char * name,uint32_t index,uint32_t total)
{
membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + 8 /*actual data*/ );
membuffer_write_atom_name(buf,name);
membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + 8 /*actual data*/ );
membuffer_write_atom_name(buf,"data");
membuffer_write_int32(buf,0);//flags
membuffer_write_int32(buf,0);//reserved
membuffer_write_int16(buf,0);
membuffer_write_int16(buf,(uint16_t)index);//track number
membuffer_write_int16(buf,(uint16_t)total);//total tracks
membuffer_write_int16(buf,0);
}
static void membuffer_write_int16_tag(membuffer * buf,const char * name,uint16_t value)
{
membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + 2 /*actual data*/ );
membuffer_write_atom_name(buf,name);
membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + 2 /*actual data*/ );
membuffer_write_atom_name(buf,"data");
membuffer_write_int32(buf,0);//flags
membuffer_write_int32(buf,0);//reserved
membuffer_write_int16(buf,value);//value
}
static void membuffer_write_std_tag(membuffer * buf,const char * name,const char * value)
{
membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value) );
membuffer_write_atom_name(buf,name);
membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value));
membuffer_write_atom_name(buf,"data");
membuffer_write_int32(buf,1);//flags
membuffer_write_int32(buf,0);//reserved
membuffer_write_data(buf,value,strlen(value));
}
static void membuffer_write_custom_tag(membuffer * buf,const char * name,const char * value)
{
membuffer_write_int32(buf,8 /*atom header*/ + 0x1C /*weirdo itunes atom*/ + 12 /*name atom header*/ + strlen(name) + 16 /*data atom header + flags*/ + strlen(value) );
membuffer_write_atom_name(buf,"----");
membuffer_write_int32(buf,0x1C);//weirdo itunes atom
membuffer_write_atom_name(buf,"mean");
membuffer_write_int32(buf,0);
membuffer_write_data(buf,"com.apple.iTunes",16);
membuffer_write_int32(buf,12 + strlen(name));
membuffer_write_atom_name(buf,"name");
membuffer_write_int32(buf,0);
membuffer_write_data(buf,name,strlen(name));
membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value));
membuffer_write_atom_name(buf,"data");
membuffer_write_int32(buf,1);//flags
membuffer_write_int32(buf,0);//reserved
membuffer_write_data(buf,value,strlen(value));
}
static uint32_t myatoi(const char * param)
{
return param ? atoi(param) : 0;
}
static uint32_t create_ilst(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
{
membuffer * buf = membuffer_create();
unsigned metaptr;
char * mask = (char*)malloc(data->count);
memset(mask,0,data->count);
{
const char * tracknumber_ptr = 0, * totaltracks_ptr = 0;
const char * discnumber_ptr = 0, * totaldiscs_ptr = 0;
const char * genre_ptr = 0, * tempo_ptr = 0;
for(metaptr = 0; metaptr < data->count; metaptr++)
{
mp4ff_tag_t * tag = &data->tags[metaptr];
if (!stricmp(tag->item,"tracknumber") || !stricmp(tag->item,"track"))
{
if (tracknumber_ptr==0) tracknumber_ptr = tag->value;
mask[metaptr] = 1;
}
else if (!stricmp(tag->item,"totaltracks"))
{
if (totaltracks_ptr==0) totaltracks_ptr = tag->value;
mask[metaptr] = 1;
}
else if (!stricmp(tag->item,"discnumber") || !stricmp(tag->item,"disc"))
{
if (discnumber_ptr==0) discnumber_ptr = tag->value;
mask[metaptr] = 1;
}
else if (!stricmp(tag->item,"totaldiscs"))
{
if (totaldiscs_ptr==0) totaldiscs_ptr = tag->value;
mask[metaptr] = 1;
}
else if (!stricmp(tag->item,"genre"))
{
if (genre_ptr==0) genre_ptr = tag->value;
mask[metaptr] = 1;
}
else if (!stricmp(tag->item,"tempo"))
{
if (tempo_ptr==0) tempo_ptr = tag->value;
mask[metaptr] = 1;
}
}
if (tracknumber_ptr) membuffer_write_track_tag(buf,"trkn",myatoi(tracknumber_ptr),myatoi(totaltracks_ptr));
if (discnumber_ptr) membuffer_write_track_tag(buf,"disk",myatoi(discnumber_ptr),myatoi(totaldiscs_ptr));
if (tempo_ptr) membuffer_write_int16_tag(buf,"tmpo",(uint16_t)myatoi(tempo_ptr));
if (genre_ptr)
{
uint32_t index = mp4ff_meta_genre_to_index(genre_ptr);
if (index==0)
membuffer_write_std_tag(buf,"©gen",genre_ptr);
else
membuffer_write_int16_tag(buf,"gnre",(uint16_t)index);
}
}
for(metaptr = 0; metaptr < data->count; metaptr++)
{
if (!mask[metaptr])
{
mp4ff_tag_t * tag = &data->tags[metaptr];
const char * std_meta_atom = find_standard_meta(tag->item);
if (std_meta_atom)
{
membuffer_write_std_tag(buf,std_meta_atom,tag->value);
}
else
{
membuffer_write_custom_tag(buf,tag->item,tag->value);
}
}
}
free(mask);
if (membuffer_error(buf))
{
membuffer_free(buf);
return 0;
}
*out_size = membuffer_get_size(buf);
*out_buffer = membuffer_detach(buf);
membuffer_free(buf);
return 1;
}
static uint32_t find_atom(mp4ff_t * f,uint64_t base,uint32_t size,const char * name)
{
uint32_t remaining = size;
uint64_t atom_offset = base;
for(;;)
{
char atom_name[4];
uint32_t atom_size;
mp4ff_set_position(f,atom_offset);
if (remaining < 8) break;
atom_size = mp4ff_read_int32(f);
if (atom_size > remaining || atom_size < 8) break;
mp4ff_read_data(f,atom_name,4);
if (!memcmp(atom_name,name,4))
{
mp4ff_set_position(f,atom_offset);
return 1;
}
remaining -= atom_size;
atom_offset += atom_size;
}
return 0;
}
static uint32_t find_atom_v2(mp4ff_t * f,uint64_t base,uint32_t size,const char * name,uint32_t extraheaders,const char * name_inside)
{
uint64_t first_base = (uint64_t)(-1);
while(find_atom(f,base,size,name))//try to find atom <name> with atom <name_inside> in it
{
uint64_t mybase = mp4ff_position(f);
uint32_t mysize = mp4ff_read_int32(f);
if (first_base == (uint64_t)(-1)) first_base = mybase;
if (mysize < 8 + extraheaders) break;
if (find_atom(f,mybase+(8+extraheaders),mysize-(8+extraheaders),name_inside))
{
mp4ff_set_position(f,mybase);
return 2;
}
base += mysize;
if (size<=mysize) {size=0;break;}
size -= mysize;
}
if (first_base != (uint64_t)(-1))//wanted atom inside not found
{
mp4ff_set_position(f,first_base);
return 1;
}
else return 0;
}
static uint32_t create_meta(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
{
membuffer * buf;
uint32_t ilst_size;
void * ilst_buffer;
if (!create_ilst(data,&ilst_buffer,&ilst_size)) return 0;
buf = membuffer_create();
membuffer_write_int32(buf,0);
membuffer_write_atom(buf,"ilst",ilst_size,ilst_buffer);
free(ilst_buffer);
*out_size = membuffer_get_size(buf);
*out_buffer = membuffer_detach(buf);
membuffer_free(buf);
return 1;
}
static uint32_t create_udta(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
{
membuffer * buf;
uint32_t meta_size;
void * meta_buffer;
if (!create_meta(data,&meta_buffer,&meta_size)) return 0;
buf = membuffer_create();
membuffer_write_atom(buf,"meta",meta_size,meta_buffer);
free(meta_buffer);
*out_size = membuffer_get_size(buf);
*out_buffer = membuffer_detach(buf);
membuffer_free(buf);
return 1;
}
static uint32_t modify_moov(mp4ff_t * f,const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
{
uint64_t total_base = f->moov_offset + 8;
uint32_t total_size = (uint32_t)(f->moov_size - 8);
uint64_t udta_offset,meta_offset,ilst_offset;
uint32_t udta_size, meta_size, ilst_size;
uint32_t new_ilst_size;
void * new_ilst_buffer;
uint8_t * p_out;
int32_t size_delta;
if (!find_atom_v2(f,total_base,total_size,"udta",0,"meta"))
{
membuffer * buf;
void * new_udta_buffer;
uint32_t new_udta_size;
if (!create_udta(data,&new_udta_buffer,&new_udta_size)) return 0;
buf = membuffer_create();
mp4ff_set_position(f,total_base);
membuffer_transfer_from_file(buf,f,total_size);
membuffer_write_atom(buf,"udta",new_udta_size,new_udta_buffer);
free(new_udta_buffer);
*out_size = membuffer_get_size(buf);
*out_buffer = membuffer_detach(buf);
membuffer_free(buf);
return 1;
}
else
{
udta_offset = mp4ff_position(f);
udta_size = mp4ff_read_int32(f);
if (find_atom_v2(f,udta_offset+8,udta_size-8,"meta",4,"ilst")<2)
{
membuffer * buf;
void * new_meta_buffer;
uint32_t new_meta_size;
if (!create_meta(data,&new_meta_buffer,&new_meta_size)) return 0;
buf = membuffer_create();
mp4ff_set_position(f,total_base);
membuffer_transfer_from_file(buf,f,(uint32_t)(udta_offset - total_base));
membuffer_write_int32(buf,udta_size + 8 + new_meta_size);
membuffer_write_atom_name(buf,"udta");
membuffer_transfer_from_file(buf,f,udta_size);
membuffer_write_atom(buf,"meta",new_meta_size,new_meta_buffer);
free(new_meta_buffer);
*out_size = membuffer_get_size(buf);
*out_buffer = membuffer_detach(buf);
membuffer_free(buf);
return 1;
}
meta_offset = mp4ff_position(f);
meta_size = mp4ff_read_int32(f);
if (!find_atom(f,meta_offset+12,meta_size-12,"ilst")) return 0;//shouldn't happen, find_atom_v2 above takes care of it
ilst_offset = mp4ff_position(f);
ilst_size = mp4ff_read_int32(f);
if (!create_ilst(data,&new_ilst_buffer,&new_ilst_size)) return 0;
size_delta = new_ilst_size - (ilst_size - 8);
*out_size = total_size + size_delta;
*out_buffer = malloc(*out_size);
if (*out_buffer == 0)
{
free(new_ilst_buffer);
return 0;
}
p_out = (uint8_t*)*out_buffer;
mp4ff_set_position(f,total_base);
mp4ff_read_data(f,p_out,(uint32_t)(udta_offset - total_base )); p_out += (uint32_t)(udta_offset - total_base );
*(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4;
mp4ff_read_data(f,p_out,4); p_out += 4;
mp4ff_read_data(f,p_out,(uint32_t)(meta_offset - udta_offset - 8)); p_out += (uint32_t)(meta_offset - udta_offset - 8);
*(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4;
mp4ff_read_data(f,p_out,4); p_out += 4;
mp4ff_read_data(f,p_out,(uint32_t)(ilst_offset - meta_offset - 8)); p_out += (uint32_t)(ilst_offset - meta_offset - 8);
*(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4;
mp4ff_read_data(f,p_out,4); p_out += 4;
memcpy(p_out,new_ilst_buffer,new_ilst_size);
p_out += new_ilst_size;
mp4ff_set_position(f,ilst_offset + ilst_size);
mp4ff_read_data(f,p_out,(uint32_t)(total_size - (ilst_offset - total_base) - ilst_size));
free(new_ilst_buffer);
}
return 1;
}
int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data)
{
void * new_moov_data;
uint32_t new_moov_size;
mp4ff_t *ff = malloc(sizeof(mp4ff_t));
memset(ff, 0, sizeof(mp4ff_t));
ff->stream = f;
mp4ff_set_position(ff,0);
parse_atoms(ff,1);
if (!modify_moov(ff,data,&new_moov_data,&new_moov_size))
{
mp4ff_close(ff);
return 0;
}
/* copy moov atom to end of the file */
if (ff->last_atom != ATOM_MOOV)
{
char *free_data = "free";
/* rename old moov to free */
mp4ff_set_position(ff, ff->moov_offset + 4);
mp4ff_write_data(ff, free_data, 4);
mp4ff_set_position(ff, ff->file_size);
mp4ff_write_int32(ff,new_moov_size + 8);
mp4ff_write_data(ff,"moov",4);
mp4ff_write_data(ff, new_moov_data, new_moov_size);
}
else
{
mp4ff_set_position(ff, ff->moov_offset);
mp4ff_write_int32(ff,new_moov_size + 8);
mp4ff_write_data(ff,"moov",4);
mp4ff_write_data(ff, new_moov_data, new_moov_size);
}
mp4ff_truncate(ff);
mp4ff_close(ff);
return 1;
}
#endif

View file

@ -0,0 +1,188 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id$
**/
#include "mp4ffint.h"
#include <stdlib.h>
int32_t mp4ff_read_data(mp4ff_t *f, int8_t *data, uint32_t size)
{
int32_t result = 1;
result = f->stream->read(f->stream->user_data, data, size);
f->current_position += size;
return result;
}
int32_t mp4ff_truncate(mp4ff_t * f)
{
return f->stream->truncate(f->stream->user_data);
}
int32_t mp4ff_write_data(mp4ff_t *f, int8_t *data, uint32_t size)
{
int32_t result = 1;
result = f->stream->write(f->stream->user_data, data, size);
f->current_position += size;
return result;
}
int32_t mp4ff_write_int32(mp4ff_t *f,const uint32_t data)
{
uint32_t result;
uint32_t a, b, c, d;
int8_t temp[4];
*(uint32_t*)temp = data;
a = (uint8_t)temp[0];
b = (uint8_t)temp[1];
c = (uint8_t)temp[2];
d = (uint8_t)temp[3];
result = (a<<24) | (b<<16) | (c<<8) | d;
return mp4ff_write_data(f,(uint8_t*)&result,sizeof(result));
}
int32_t mp4ff_set_position(mp4ff_t *f, const int64_t position)
{
f->stream->seek(f->stream->user_data, position);
f->current_position = position;
return 0;
}
int64_t mp4ff_position(const mp4ff_t *f)
{
return f->current_position;
}
uint64_t mp4ff_read_int64(mp4ff_t *f)
{
uint8_t data[8];
uint64_t result = 0;
int8_t i;
mp4ff_read_data(f, data, 8);
for (i = 0; i < 8; i++)
{
result |= ((uint64_t)data[i]) << ((7 - i) * 8);
}
return result;
}
uint32_t mp4ff_read_int32(mp4ff_t *f)
{
uint32_t result;
uint32_t a, b, c, d;
int8_t data[4];
mp4ff_read_data(f, data, 4);
a = (uint8_t)data[0];
b = (uint8_t)data[1];
c = (uint8_t)data[2];
d = (uint8_t)data[3];
result = (a<<24) | (b<<16) | (c<<8) | d;
return (uint32_t)result;
}
uint32_t mp4ff_read_int24(mp4ff_t *f)
{
uint32_t result;
uint32_t a, b, c;
int8_t data[4];
mp4ff_read_data(f, data, 3);
a = (uint8_t)data[0];
b = (uint8_t)data[1];
c = (uint8_t)data[2];
result = (a<<16) | (b<<8) | c;
return (uint32_t)result;
}
uint16_t mp4ff_read_int16(mp4ff_t *f)
{
uint32_t result;
uint32_t a, b;
int8_t data[2];
mp4ff_read_data(f, data, 2);
a = (uint8_t)data[0];
b = (uint8_t)data[1];
result = (a<<8) | b;
return (uint16_t)result;
}
char * mp4ff_read_string(mp4ff_t * f,uint32_t length)
{
char * str = (char*)malloc(length + 1);
if (str!=0)
{
if ((uint32_t)mp4ff_read_data(f,str,length)!=length)
{
free(str);
str = 0;
}
else
{
str[length] = 0;
}
}
return str;
}
uint8_t mp4ff_read_char(mp4ff_t *f)
{
uint8_t output;
mp4ff_read_data(f, &output, 1);
return output;
}
uint32_t mp4ff_read_mp4_descr_length(mp4ff_t *f)
{
uint8_t b;
uint8_t numBytes = 0;
uint32_t length = 0;
do
{
b = mp4ff_read_char(f);
numBytes++;
length = (length << 7) | (b & 0x7F);
} while ((b & 0x80) && numBytes < 4);
return length;
}

View file

@ -0,0 +1,11 @@
Marcus Heese
marc.icq@gmx.de
icq : 126202773
and very special thanks to...
Frederic Fondriest
icq : 17293220
irc : /server irc.eu.freenode.net /join #lamip
...for a linux audio player with a very good API! :)

View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -0,0 +1,6 @@
lamip-inputSHORTEN_20050405:
- fixed a few minor things. Some variables have to be declared static!
lamip-inputSHORTEN_20050324:
- well.... it is the initial release!

View file

@ -0,0 +1 @@
SUBDIRS = shorten src

View file

@ -0,0 +1,2 @@
well... who the hell takes a look in all these damn files?!?

View file

@ -0,0 +1,45 @@
LAMIP-0.0.3 SHORTEN decoder
---------------------------
This is a shorten decoder for lamip. SHORTEN has been a widely used lossless
codec. Since version 3 shorten has seeking support through seek tables (.skt).
They can also be merged into the shorten file (.shn). The code for this plugin
derives from the xmms shorten plugin version 2.4.0 written by Jason Jordan.
Look at that homepage:
http://etree.org/shnutils/shorten/
I have redesigned the xmms-shn plugin for a libshorten decoding library. You
should be able to install libshorten as a standalone-lib and decode shorten
files through that library
Config options
--------------
- error_output_method: can be STDERR and DEVNULL... I think the names are
self explanatory
- swap_bytes: If you have a big-endian machine, switch it on!
- verbose: It is for some verbose debugging messages in the integrated logging
facility of libshorten
- seek_tables_path: An absolute path to a directory which contains shorten seek-
tables
- relative_seek_tables_path: A relative path to directories which contain
shorten seek-tables
INSTALL
-------
run :
- autoreconf -vifs
- ./configure --enable-debug
- make
and as root :
- make install or make install-strip
----------
marc.icq@gmx.de

View file

@ -0,0 +1,7 @@
for the future:
---------------
- implement id3v2 tag reading, perhaps... :)
- link against a released libshorten (static development version used in this plugin by now)
- documentation for libshorten

View file

@ -0,0 +1,78 @@
dnl configure.in for lamip-0.0.3 shorten input plugin
AC_INIT(libinputshorten, 0.0.3)
AC_CONFIG_SRCDIR(src/libinputshorten.c)
AM_INIT_AUTOMAKE(inputSHORTEN, 0.0.3)
AM_CONFIG_HEADER(shorten/include/config.h)
dnl AC_INIT(src/libinputshorten.c)
dnl AM_INIT_AUTOMAKE(libinputshorten, 0.0.3)
AM_DISABLE_STATIC
dnl save CFLAGS since AC_PROG_CC insert "-g -O2" if CFLAGS is empty
cflags_save="$CFLAGS"
AC_PROG_CC
AC_PROG_CXX
AC_PROG_AWK
AC_PROG_LN_S
AC_PROG_INSTALL
AC_LIBTOOL_DLOPEN
AM_PROG_LIBTOOL
AC_HEADER_STDC
AC_CHECK_LIB(m, main)
AC_HEADER_STDC
AC_CHECK_HEADERS(stdarg.h inttypes.h dirent.h)
AC_CHECK_SIZEOF(unsigned long)
AC_FUNC_SETVBUF_REVERSED
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(opendir readdir closedir strerror vsnprintf)
AC_CHECK_PROGS(LAMIP, lamip,
AC_MSG_ERROR(*** lamip not found))
CFLAGS="$cflags_save -Wall `lamip --cflags`"
CPPFLAGS="$CPPFLAGS $CFLAGS"
AC_SUBST(CFLAGS)
cflags_save="$CFLAGS"
AC_CHECK_HEADER(lamip.h,,
AC_MSG_ERROR(*** LAMIP headers not found check your CFLAGS))
CFLAGS="$cflags_save -I. -I.. -Ishorten/include"
cflags_save="$CFLAGS"
AC_SUBST(CFLAGS)
AC_ARG_ENABLE(debug,
[ --enable-debug (for developers only... and people with probs!) ],
[enable_debug=$enableval],
[enable_debug="no"])
if test "x$enable_debug" = xyes; then
CPPFLAGS="$CPPFLAGS -DDEBUG"
CFLAGS="$CFLAGS -g"
AC_MSG_RESULT([*** Debugging is enabled... ])
fi
AC_OUTPUT([Makefile shorten/Makefile shorten/util/Makefile shorten/src/Makefile src/Makefile])
echo ""
echo "*** LAMIP inputSHORTEN (Shorten Codec) plugin succefully configured ***"
echo ""
echo "This plugin allows you to play *.shn files..."
echo ""
echo "install-dir : `lamip --plugin-dir`"
echo ""
echo "CFLAGS : $CFLAGS"
echo "LDFLAGS : $LDFLAGS"
echo "CPPFLAGS : $CPPFLAGS"
echo ""
if test "x$enable_debug" = xyes; then
echo "- debugging messages are enabled!"
echo ""
fi

View file

@ -0,0 +1 @@
SUBDIRS = util src

View file

@ -0,0 +1,20 @@
SHORTEN SOFTWARE LICENSE
This software is being provided to you, the LICENSEE, by Tony Robinson
and SoftSound under the following license. By obtaining, using and/or
copying this software, you agree that you have read, understood, and
will comply with these terms and conditions:
This software may not be sold or incorporated into any product which is
sold without prior permission from SoftSound. When no charge is made,
this software may be copied and distributed freely.
Permission is granted to use this software for decoding and
non-commercial encoding (e.g. private or research use). Please email
shorten@softsound.com for commercial encoding terms.
DISCLAIMER
This software carries no warranty, expressed or implied. The user
assumes all risks, known or unknown, direct or indirect, which involve
this software in any way.

View file

@ -0,0 +1 @@
Jason Jordan <shnutils@freeshell.org>

View file

@ -0,0 +1,39 @@
Thanks goes to the XMMS development team, as version 0.x through 1.x of this
plugin were originally based on the Input/wav/wav.[ch] files from the XMMS
distribution.
Thanks also goes to Caleb Epstein for testing and reporting bugs, and for
providing .deb and .rpm packages.
Wayne Stielau provided specs and code that became the basis of the 2.x version
of this plugin. Without his help, this version would have taken much longer to
write.
Thanks goes to scottv for reporting a crash-inducing bug, as well as providing
me a way to download the file that caused it for analysis.
Thanks goes to Daniel Robbins for reporting the truncated-scope bug.
Thanks goes to Paul Mather for reporting the m:ss.ff rounding bug in shntool
(which also affected xmms-shn), as well as providing a detailed analysis of the
problem which expedited its fix.
Thanks goes to Ari Pollak for reporting a crash that led to the discovery of a
race condition in the .shn unloading code.
Thanks to Alex Prestin for sending a byte-swap patch that fixed a problem where
all files would play back as static on his Ultra 10 and Ultra 30, as well as
providing a patch to load text files in the file information box, which became
the basis of the current implementation.
Thanks to Rhett Monteg Hollander for reporting a bug that prevented xmms-shn
from playing files encoded with alternate options, e.g. "-b1280 -p16 -m4".
Thanks to Peter Kunath for sending a one-line patch to fix a bug in shorten that
caused incorrect seek tables to be generated under certain conditions, as well
as for providing a way for xmms-shn to automatically detect this bug so that it
can disable seeking in affected files.
Finally, thanks goes to SoftSound for creating a great waveform encoder,
shorten, and especially for providing the source code to it. Without the
source, there would be no seek-enabled versions of shorten, and no xmms-shn 2.x.

View file

@ -0,0 +1 @@
No news is good news.

View file

@ -0,0 +1,346 @@
xmms-shn version 2.4.x
--------
Overview
--------
xmms-shn provides playback support for shorten (.shn) files in XMMS. Real-time
seeking support is provided for .shn files that have accompanying seek tables
generated by shorten 3.x. Otherwise, seeking is not supported.
See the "Shorten 3.x overview" section below for more information about this new
seek-enabled version of shorten.
------------
Availability
------------
The latest version of this plugin can always be found at the sites below:
http://www.etree.org/shnutils/
http://shnutils.freeshell.org/
Please see the ChangeLog file for changes to this plugin since its creation.
------------
Dependencies
------------
As of version 2.0, xmms-shn no longer depends on an external shorten executable
to work, since the core shorten algorithm has been incorporated directly into
xmms-shn.
You should have XMMS 1.0.0 or newer, and GTK & GLIB 1.2.2 or newer. The
configure script will usually find these if you installed them from source.
However, if you installed any of the above via .rpm's, then you may need to tell
the configure script where to find them. To see what options are available,
type:
% ./configure --help
The applicable options are the following:
--with-xmms-prefix=PFX Prefix where XMMS is installed (optional)
--with-xmms-exec-prefix=PFX Exec prefix where XMMS is installed (optional)
--with-glib-prefix=PFX Prefix where GLIB is installed (optional)
--with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)
--disable-glibtest Do not try to compile and run a test GLIB program
--with-gtk-prefix=PFX Prefix where GTK is installed (optional)
--with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)
--disable-gtktest Do not try to compile and run a test GTK program
-----------------------------------
Building and installing this plugin
-----------------------------------
For instructions on how to build and install this plugin, please consult the
INSTALL file. It is usually as simple as the following:
% ./configure
% make
% su -c "make install"
Password: (give your root password here)
%
---------------------
Configuration options
---------------------
This section details the options that can be found in the plugin's configuration
window in XMMS, under Preferences -> Audio I/O Plugins -> SHN Player 2.4.x ->
Configure.
Error Display tab:
==================
Error display options:
----------------------
This option determines where any error messages go - to a popup window,
to standard error, or to the bit bucket. Pretty self-explanatory.
Seek Tables tab:
================
Alternate seek table file locations:
------------------------------------
These options allow you to specify alternate directores to search for .skt
(seek table) files. These directories will be searched after all other attempts
to locate a seek table for a given file have failed.
The "Relative seek table path" option allows you to specify a subdirectory
relative to the base directory of a given file, where seek tables may reside.
This is useful if you create seek table files for a group of .shn files, and
store them in a commonly-named subdirectory of that group.
The "Absolute seek table path" option allows you to specify an absolute directory
where seek tables may reside. This is useful if you create seek table files for
multiple groups of .shn files and store them in the same directory.
When searching for seek tables belonging to a file (e.g. '/mnt/shn/filename.shn'),
xmms-shn will do the following, in this order, until it either finds a seek table
or runs out of places to check for one:
1. look for a seek table appended to '/mnt/shn/filename.shn' (whether at the end,
or hidden behind an ID3v1 tag)
2. look for a seek table in '/mnt/shn/filename.skt'
3. look for a seek table in '/mnt/shn/relative_dir/filename.skt', where
'relative_dir' is the directory specified in the "Relative seek table path"
option
4. look for a seek table in '/absolute_dir/filename.skt', where 'absolute_dir'
is the directory specified in the "Absolute seek table path" option
Miscellaneous tab:
==================
Miscellaneous options:
----------------------
The "Swap audio bytes on output" option is useful in situations where every file
you play back is static. This is known to help on the following platforms:
+ Sun Ultra 10 and Ultra 30 both running Solaris 8
+ SGI Octane/Irix 6.5
The "Display debug info to stderr" option specifies whether to display debugging
messages to stderr. This is potentially useful for remote debugging, and also
just to see what's going on. Debug lines are always shown with a prefix of
"xmms-shn [debug]:".
Note that if "Display debug info to stderr" is enabled, and the error display
option is set to /dev/null, then all non-debug messages that normally would be
suppressed are displayed to stderr with a prefix of "xmms-shn [error]:".
The "Load text files in file information box" option specifies whether text files
found in the same or parent directory as the given file should be loaded into the
file information box. Each file found will be loaded in a separate tab. The tabs
will be labeled "Text file n", where n starts at 1 and increases with each new
text file.
The "Text file extensions" option lets you specify a comma-separated list of case-
sensitive file extensions that xmms-shn will recognize as text files. The default
list is "txt,nfo". This option is only useful if "Load text files in file
information box" is enabled.
Note:
Text file support is useful for quickly determining information about the given
file and/or the show it belongs to, assuming such information is contained within
the text files.
Text file location assumes some combination of the following two directory
structures: all text files and .shn files in the same directory, or text files
in a directory with all .shn files in subdirectories one level deep. This
pretty much covers all directory structures seen on live music servers and file-
sharing programs.
--------------------
File information box
--------------------
This section describes the output shown in the file information window, which
can be viewed by choosing 'File Inf.' from the 'Misc. Opt' button in the
playlist editor, or selecting 'View File Info' from XMMS's main popup menu.
Properties tab:
===============
Filename: Shows the full path to the .shn file being examined.
Length: Shows the length of the WAVE data in the file, in m:ss.nnn format.
If the WAVE data is CD-quality (see below for definition), then the length is
shown in m:ss.ff format, where ff is a number from 00 to 74 that best
approximates the number of frames (2352-byte blocks) remaining after m:ss.
Note on rounding: If the WAVE data is CD-quality, then its length is
rounded to the nearest frame. Otherwise, it is rounded
to the nearest millisecond.
Seekable: Shows whether a seek table was found for the given file.
Seek table revision: Shows the revision number of the seek tables, if
present. Note that it is possible for this field to contain a numeric value,
even when the file is not seekable - for example, xmms-shn might detect that
certain seek tables are buggy, and disable seeking in those files.
Compression ratio: Shows the compression ratio for the given file. This is
simply the file's actual size divided by its total size, as calculated from
the chunk size contained in the WAVE header. Note that if the given file is
truncated (or has junk appended to it), then the compression ratio will be
skewed accordingly.
CD-quality properties:
----------------------
CD-quality: Shows whether the given file is CD-quality. A file is considered
to be CD-quality if its header indicates 2 channels, 16 bits/sample, 44100
samples/second, and 176400 average bytes/second.
Cut on a sector boundary: If the given file is CD-quality, then this shows
whether the length of its WAVE data is a multiple of 2352 bytes (1/75 of a
second). Otherwise, "n/a" is displayed.
Sector misalignemt: If the file is CD-quality, then the sector misalignment
is simply the remainder when the data size is divided by 2352; i.e. it is the
number of bytes by which the audio data exceeds the previous sector boundary.
Long enough to be burned: If the given file is CD-quality, then this shows
whether the length of its WAVE data is long enough to be burned (705600 bytes,
or 3 seconds in length). Otherwise, "n/a" is displayed.
WAVE properties:
----------------
Non-canonical header: Shows whether the WAVE header is canonical. A header
is considered canonical if it is 44 bytes long (this is the smallest possible
size that a WAVE header can be).
Extra RIFF chunks: Shows whether there are any extra RIFF chunks following
the data chunk in the WAVE stream.
Possible problems:
------------------
File contains ID3v2 tag: Shows whether the file contains an ID3v2 tag, and
if so, how many bytes it occupies. This is not a problem for xmms-shn (it
was able to read the file after all), but could pose a problem for programs
that are not able to process files with ID3v2 tags.
Details tab:
============
This tab primarily shows the raw information taken from the WAVE header of the
given file. Each entry is self-explanatory.
Text file n tab(s):
===================
These tabs, if any, show the contents of all text files found in the same
directory or parent directory as the given file. The associated file name for
each tab is contained in the frame surrounding the text, and the full path to
the file being displayed is shown just above the text. You can control which
files are considered to be text files with the "Text file extensions" option in
the configuration window. Make sure to select the "Load text files in file
information box" option if you want to see these tabs.
--------------------
Shorten 3.x overview
--------------------
Wayne Stielau has extended shorten 2.3 to support the creation of seek tables.
Seek tables are simply descriptions of the internal state of the shorten
algorithm at specific points in the decompression. This allows a modified
shorten decoder to restore the decoder state of the shorten algorithm for a
point at (or very close to) the desired seek point. You can get the latest
version at any of the URLs below:
http://www.etree.org/shnutils/shorten/
http://shnutils.freeshell.org/shorten/
Seek tables may be appended to the .shn itself, or stored in a separate file
(usually with a suffix of '.skt'). xmms-shn supports both of these options.
The current implementation creates a seek table entry once every 25600 samples.
For 'CD-quality' WAVE data (44100 samples/sec), this provides a granularity of 1
seek table entry per 25600/44100 ~= 0.58 seconds, more than what is needed by
either XMMS or WinAmp.
At 80 bytes per seek table entry, you can expect the seek table to add about
0.1% to the size of the existing shortened file, for 'CD-quality' WAVE data.
So the seek table generated for 1 GB of already-shortened 'CD-quality' WAVE data
will fit on a floppy! Quite a deal, if you ask me. :-)
Best of all, shorten 3.x is fully backward compatible with version 2.3, meaning
that any files created by shorten 3.x can be processed by version 2.3 with no
problems.
The command line options for dealing with seek tables in shorten 3.x are:
-e erase seek table appended to input file *
-i inquire as to whether a seek table is appended to input file *
-k append seek table information to existing shorten file
-s generate seek table information in separate file [input file].skt
-S[name] generate seek table information in separate file given by [name]
-v 3 format version number (2: no seek info; 3: default) *
* only available in versions 3.2 and up
By default, any file shortened with version 3.x will automatically have seek
tables appended to it. In later versions (3.2 and up), you can disable this
with the -v2 switch.
** NOTE ON SEEKING IN FILES ENCODED WITH NON-DEFAULT OPTIONS **
Seek tables generated by shorten for files that were encoded with non-default
options do not seem to work correctly in most cases. Normal playback works
fine, but any attempt to seek within such a file may cause the audio to become
garbled. This appears to be due to an unforseen limitation in the design of
seek table generation in shorten - for example, as stated above, seek tables
were intended to be generated once every 25600 samples, but this is not true if
an alternate block size is given with the -b option. Encoding options that seem
to be able to cause this problem when set to non-default values are the -b, -m
and -p options. Since there is no reliable way to identify such files, the best
xmms-shn can do is attempt to seek based on the values in the seek tables. If
the sound becomes garbled, then you have likely run across one of these files,
and are out of luck.
----------
Known bugs
----------
1. Not really a bug in xmms-shn, but under certain conditions, seeking may not
work correctly. The primary symptom of this is garbled audio after a seek is
performed. See the section above titled "NOTE ON SEEKING IN FILES ENCODED
WITH NON-DEFAULT OPTIONS" for more information.
I test this plugin aggressively until I can no longer make it crash. That does
not mean that there are no bugs. If you can crash it, I want to hear about it -
please report it to me at the address below. The xmms-shn webpage (see the
Availability section above) will always contain an up-to-date list of reported
bugs, so be sure to check that page before you send me a bug report.
Also, feel free to send me any questions, comments, feature requests, patches...
I always enjoy getting feedback.
Enjoy!
Jason Jordan <shnutils@freeshell.org>

View file

@ -0,0 +1,33 @@
char ulaw_maxshift[256] = {12,8,7,9,7,8,7,10,7,8,7,9,7,8,7,11,6,7,6,8,6,7,6,9,6,7,6,8,6,7,6,10,5,6,5,7,5,6,5,8,5,6,5,7,5,6,5,9,5,4,6,4,5,4,7,4,5,4,6,4,5,4,8,4,3,5,3,4,3,6,3,4,3,5,3,4,3,7,3,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,0,7,8,7,9,7,8,7,10,7,8,7,9,7,8,7,11,6,7,6,8,6,7,6,9,6,7,6,8,6,7,6,10,5,6,5,7,5,6,5,8,5,6,5,7,5,6,5,9,5,4,6,4,5,4,7,4,5,4,6,4,5,4,8,4,3,5,3,4,3,6,3,4,3,5,3,4,3,7,3,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,12};
schar ulaw_inward[13][256] = {
{-127,-126,-125,-124,-123,-122,-121,-120,-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,-128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0},
{-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-128,-7,-127,-6,-126,-5,-125,-4,-124,-3,-123,-2,-122,-1,-121,-120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,127,7,126,6,125,5,124,4,123,3,122,2,121,1,120,0},
{-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-128,-11,-127,-10,-126,-9,-125,-8,-124,-7,-123,-6,-122,-5,-121,-4,-120,-119,-118,-3,-117,-116,-115,-2,-114,-113,-112,-1,-111,-110,-109,-108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,127,11,126,10,125,9,124,8,123,7,122,6,121,5,120,4,119,118,117,3,116,115,114,2,113,112,111,1,110,109,108,0},
{-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-128,-13,-127,-12,-126,-11,-125,-10,-124,-9,-123,-8,-122,-7,-121,-6,-120,-119,-118,-5,-117,-116,-115,-4,-114,-113,-112,-3,-111,-110,-109,-2,-108,-107,-106,-105,-104,-103,-102,-1,-101,-100,-99,-98,-97,-96,-95,-94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,127,13,126,12,125,11,124,10,123,9,122,8,121,7,120,6,119,118,117,5,116,115,114,4,113,112,111,3,110,109,108,2,107,106,105,104,103,102,101,1,100,99,98,97,96,95,94,0},
{-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-128,-14,-127,-13,-126,-12,-125,-11,-124,-10,-123,-9,-122,-8,-121,-7,-120,-119,-118,-6,-117,-116,-115,-5,-114,-113,-112,-4,-111,-110,-109,-3,-108,-107,-106,-105,-104,-103,-102,-2,-101,-100,-99,-98,-97,-96,-95,-1,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,127,14,126,13,125,12,124,11,123,10,122,9,121,8,120,7,119,118,117,6,116,115,114,5,113,112,111,4,110,109,108,3,107,106,105,104,103,102,101,2,100,99,98,97,96,95,94,1,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,0},
{-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-128,-14,-127,-13,-126,-12,-125,-11,-124,-10,-123,-9,-122,-8,-121,-120,-7,-119,-118,-117,-6,-116,-115,-114,-5,-113,-112,-111,-4,-110,-109,-108,-107,-106,-3,-105,-104,-103,-102,-101,-100,-99,-2,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-1,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,127,14,126,13,125,12,124,11,123,10,122,9,121,8,120,119,7,118,117,116,6,115,114,113,5,112,111,110,4,109,108,107,106,105,3,104,103,102,101,100,99,98,2,97,96,95,94,93,92,91,90,89,88,87,1,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,0},
{-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-128,-15,-127,-14,-126,-13,-125,-12,-124,-11,-123,-10,-122,-9,-121,-8,-120,-119,-7,-118,-117,-116,-6,-115,-114,-113,-5,-112,-111,-110,-4,-109,-108,-107,-106,-105,-104,-3,-103,-102,-101,-100,-99,-98,-97,-2,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-1,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,7,117,116,115,6,114,113,112,5,111,110,109,4,108,107,106,105,104,103,3,102,101,100,99,98,97,96,2,95,94,93,92,91,90,89,88,87,86,85,84,83,1,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,0},
{-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-128,-15,-127,-14,-126,-13,-125,-12,-124,-11,-123,-10,-122,-9,-121,-8,-120,-119,-118,-7,-117,-116,-115,-6,-114,-113,-112,-5,-111,-110,-109,-4,-108,-107,-106,-105,-104,-103,-3,-102,-101,-100,-99,-98,-97,-96,-2,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-1,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,117,7,116,115,114,6,113,112,111,5,110,109,108,4,107,106,105,104,103,102,3,101,100,99,98,97,96,95,2,94,93,92,91,90,89,88,87,86,85,84,83,82,81,1,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,0},
{-16,-15,-128,-14,-127,-13,-126,-12,-125,-11,-124,-10,-123,-9,-122,-8,-121,-120,-119,-7,-118,-117,-116,-6,-115,-114,-113,-5,-112,-111,-110,-4,-109,-108,-107,-106,-105,-104,-103,-3,-102,-101,-100,-99,-98,-97,-96,-2,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-1,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,117,7,116,115,114,6,113,112,111,5,110,109,108,4,107,106,105,104,103,102,101,3,100,99,98,97,96,95,94,2,93,92,91,90,89,88,87,86,85,84,83,82,81,80,1,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,0},
{-8,-128,-127,-7,-126,-125,-124,-6,-123,-122,-121,-5,-120,-119,-118,-4,-117,-116,-115,-114,-113,-112,-111,-3,-110,-109,-108,-107,-106,-105,-104,-2,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-1,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,127,126,125,7,124,123,122,6,121,120,119,5,118,117,116,4,115,114,113,112,111,110,109,3,108,107,106,105,104,103,102,2,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,1,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,0},
{-4,-128,-127,-126,-125,-124,-123,-3,-122,-121,-120,-119,-118,-117,-116,-2,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-1,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,127,126,125,124,123,122,121,3,120,119,118,117,116,115,114,2,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,1,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,0},
{-2,-128,-127,-126,-125,-124,-123,-122,-121,-120,-119,-118,-117,-116,-115,-1,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,1,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,0},
{-1,-128,-127,-126,-125,-124,-123,-122,-121,-120,-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}
};
uchar ulaw_outward[13][256] = {
{127,0,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,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128},
{112,114,116,118,120,122,124,126,127,0,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,113,115,117,119,121,123,125,255,253,251,249,247,245,243,241,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,252,250,248,246,244,242,240},
{96,98,100,102,104,106,108,110,112,113,114,116,117,118,120,121,122,124,125,126,127,0,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,97,99,101,103,105,107,109,111,115,119,123,255,251,247,243,239,237,235,233,231,229,227,225,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,250,249,248,246,245,244,242,241,240,238,236,234,232,230,228,226,224},
{80,82,84,86,88,90,92,94,96,97,98,100,101,102,104,105,106,108,109,110,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,0,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,81,83,85,87,89,91,93,95,99,103,107,111,119,255,247,239,235,231,227,223,221,219,217,215,213,211,209,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,246,245,244,243,242,241,240,238,237,236,234,233,232,230,229,228,226,225,224,222,220,218,216,214,212,210,208},
{64,66,68,70,72,74,76,78,80,81,82,84,85,86,88,89,90,92,93,94,96,97,98,99,100,101,102,104,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,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,65,67,69,71,73,75,77,79,83,87,91,95,103,111,255,239,231,223,219,215,211,207,205,203,201,199,197,195,193,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,238,237,236,235,234,233,232,230,229,228,227,226,225,224,222,221,220,218,217,216,214,213,212,210,209,208,206,204,202,200,198,196,194,192},
{49,51,53,55,57,59,61,63,64,66,67,68,70,71,72,74,75,76,78,79,80,81,82,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,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,50,52,54,56,58,60,62,65,69,73,77,83,91,103,255,231,219,211,205,201,197,193,190,188,186,184,182,180,178,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,210,209,208,207,206,204,203,202,200,199,198,196,195,194,192,191,189,187,185,183,181,179,177},
{32,34,36,38,40,42,44,46,48,49,51,52,53,55,56,57,59,60,61,63,64,65,66,67,68,70,71,72,73,74,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,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,0,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,33,35,37,39,41,43,45,47,50,54,58,62,69,77,91,255,219,205,197,190,186,182,178,175,173,171,169,167,165,163,161,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,196,195,194,193,192,191,189,188,187,185,184,183,181,180,179,177,176,174,172,170,168,166,164,162,160},
{16,18,20,22,24,26,28,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,51,52,53,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,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,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,19,21,23,25,27,29,31,35,39,43,47,54,62,77,255,205,190,182,175,171,167,163,159,157,155,153,151,149,147,145,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,181,180,179,178,177,176,174,173,172,170,169,168,166,165,164,162,161,160,158,156,154,152,150,148,146,144},
{2,4,6,8,10,12,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,35,36,37,38,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,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,0,1,3,5,7,9,11,13,15,19,23,27,31,39,47,62,255,190,175,167,159,155,151,147,143,141,139,137,135,133,131,129,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,166,165,164,163,162,161,160,158,157,156,154,153,152,150,149,148,146,145,144,142,140,138,136,134,132,130,128},
{1,2,4,5,6,8,9,10,12,13,14,16,17,18,19,20,21,22,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,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,0,3,7,11,15,23,31,47,255,175,159,151,143,139,135,131,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,150,149,148,147,146,145,144,142,141,140,138,137,136,134,133,132,130,129,128},
{1,2,3,4,5,6,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,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,0,7,15,31,255,159,143,135,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,134,133,132,131,130,129,128},
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,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,0,15,255,143,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128},
{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,0,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}
};

View file

@ -0,0 +1,96 @@
/* shorten/include/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the `closedir' function. */
#define HAVE_CLOSEDIR 1
/* Define to 1 if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `m' library (-lm). */
#define HAVE_LIBM 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `opendir' function. */
#define HAVE_OPENDIR 1
/* Define to 1 if you have the `readdir' function. */
#define HAVE_READDIR 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Name of package */
#define PACKAGE "libshorten"
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if the C compiler supports function prototypes. */
#undef PROTOTYPES
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if the `setvbuf' function takes the buffering type as its
second argument and the buffer pointer as the third, as on System V before
release 3. */
#undef SETVBUF_REVERSED
/* The size of a `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "unknown-cog"
/* Define like PROTOTYPES; this can be used by system headers. */
#undef __PROTOTYPES

View file

@ -0,0 +1,96 @@
/* shorten/include/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the `closedir' function. */
#undef HAVE_CLOSEDIR
/* Define to 1 if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `opendir' function. */
#undef HAVE_OPENDIR
/* Define to 1 if you have the `readdir' function. */
#undef HAVE_READDIR
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if the C compiler supports function prototypes. */
#undef PROTOTYPES
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if the `setvbuf' function takes the buffering type as its
second argument and the buffer pointer as the third, as on System V before
release 3. */
#undef SETVBUF_REVERSED
/* The size of a `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define like PROTOTYPES; this can be used by system headers. */
#undef __PROTOTYPES

View file

@ -0,0 +1,45 @@
#ifndef _DECODE_H
#define _DECODE_H
#include "shorten.h"
#include "shn.h"
#define NUM_DEFAULT_BUFFER_BLOCKS 512L
#ifndef _SHN_CONFIG
#define _SHN_CONFIG
/* First fill out a shn_config struct... */
typedef struct _shn_config
{
int error_output_method;
char *seek_tables_path;
char *relative_seek_tables_path;
int verbose;
int swap_bytes;
} shn_config;
#endif
/* ... then you can load a file, normally you have to use the functions in this order */
shn_file *shn_load(char *filename, shn_config config); /* Loads the file in filename and uses config... returns a shn_file context */
int shn_init_decoder(shn_file *this_shn); /* inits the decoder for this_shn necessary to do shn_read() */
/* shn_get_buffer_block_size() returns the minimal size that read_buffer should have *
* blocks should be around 512 *
* You have to allocate a buffer with the size returned by shn_get_buffer_block_size() yourself */
int shn_get_buffer_block_size(shn_file *this_shn, int blocks);
unsigned int shn_get_song_length(shn_file *this_shn); /* returns song length in milliseconds */
unsigned int shn_get_samplerate(shn_file *this_shn); /* returns the number of samples per second */
unsigned int shn_get_channels(shn_file *this_shn); /* returns the number of channels of the audio file */
unsigned int shn_get_bitspersample(shn_file *this_shn); /* returns the number of bits per sample */
/* Play with the shorten file */
int shn_read(shn_file *this_shn, uchar *read_buffer, int bytes_to_read); /* bytes_to_read should be the size returned by shn_get_buffer_block_size */
int shn_seekable(shn_file *this_shn); /* Returns 1 if file is seekables (has seek tables) otherwise 0 */
int shn_seek(shn_file *this_shn, unsigned int time); /* Seek to position "time" in seconds */
/* Unload everything */
int shn_cleanup_decoder(shn_file *this_shn); /* Frees some buffers */
void shn_unload(shn_file *this_shn); /* Unloads the file */
#endif

View file

@ -0,0 +1,284 @@
/* xmms-shn - a shorten (.shn) plugin for XMMS
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#ifndef _SHN_H
#define _SHN_H
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef HAVE_STRERROR
extern char *sys_errlist[];
#define strerror(x) sys_errlist[x]
#endif
#ifdef HAVE_VSNPRINTF
#define shn_vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
#else
#define shn_vsnprintf(a,b,c,d) vsprintf(a,c,d)
#endif
#define min(a,b) (((a)<(b))?(a):(b))
/* surely no headers will be this large. right? RIGHT? */
#define OUT_BUFFER_SIZE 16384
#define BUF_SIZE 4096
#define ERROR_OUTPUT_DEVNULL 0
#define ERROR_OUTPUT_STDERR 1
#define ERROR_OUTPUT_WINDOW 2
#define SEEK_SUFFIX "skt"
#define NO_SEEK_TABLE -1
#define SEEK_HEADER_SIGNATURE "SEEK"
#define SEEK_TRAILER_SIGNATURE "SHNAMPSK"
#define SEEK_HEADER_SIZE 12
#define SEEK_TRAILER_SIZE 12
#define SEEK_ENTRY_SIZE 80
#define SEEK_RESOLUTION 25600
#define WAVE_RIFF (0x46464952) /* 'RIFF' in little-endian */
#define WAVE_WAVE (0x45564157) /* 'WAVE' in little-endian */
#define WAVE_FMT (0x20746d66) /* ' fmt' in little-endian */
#define WAVE_DATA (0x61746164) /* 'data' in little-endian */
#define AIFF_FORM (0x4D524F46) /* 'FORM' in little-endian */
#define WAVE_FORMAT_UNKNOWN (0x0000)
#define WAVE_FORMAT_PCM (0x0001)
#define WAVE_FORMAT_ADPCM (0x0002)
#define WAVE_FORMAT_IEEE_FLOAT (0x0003)
#define WAVE_FORMAT_ALAW (0x0006)
#define WAVE_FORMAT_MULAW (0x0007)
#define WAVE_FORMAT_OKI_ADPCM (0x0010)
#define WAVE_FORMAT_IMA_ADPCM (0x0011)
#define WAVE_FORMAT_DIGISTD (0x0015)
#define WAVE_FORMAT_DIGIFIX (0x0016)
#define WAVE_FORMAT_DOLBY_AC2 (0x0030)
#define WAVE_FORMAT_GSM610 (0x0031)
#define WAVE_FORMAT_ROCKWELL_ADPCM (0x003b)
#define WAVE_FORMAT_ROCKWELL_DIGITALK (0x003c)
#define WAVE_FORMAT_G721_ADPCM (0x0040)
#define WAVE_FORMAT_G728_CELP (0x0041)
#define WAVE_FORMAT_MPEG (0x0050)
#define WAVE_FORMAT_MPEGLAYER3 (0x0055)
#define WAVE_FORMAT_G726_ADPCM (0x0064)
#define WAVE_FORMAT_G722_ADPCM (0x0065)
#define CD_BLOCK_SIZE (2352)
#define CD_BLOCKS_PER_SEC (75)
#define CD_MIN_BURNABLE_SIZE (705600)
#define CD_CHANNELS (2)
#define CD_SAMPLES_PER_SEC (44100)
#define CD_BITS_PER_SAMPLE (16)
#define CD_RATE (176400)
#define CANONICAL_HEADER_SIZE (44)
#define PROBLEM_NOT_CD_QUALITY (0x00000001)
#define PROBLEM_CD_BUT_BAD_BOUND (0x00000002)
#define PROBLEM_CD_BUT_TOO_SHORT (0x00000004)
#define PROBLEM_HEADER_NOT_CANONICAL (0x00000008)
#define PROBLEM_EXTRA_CHUNKS (0x00000010)
#define PROBLEM_HEADER_INCONSISTENT (0x00000020)
#define PROB_NOT_CD(f) ((f.problems) & (PROBLEM_NOT_CD_QUALITY))
#define PROB_BAD_BOUND(f) ((f.problems) & (PROBLEM_CD_BUT_BAD_BOUND))
#define PROB_TOO_SHORT(f) ((f.problems) & (PROBLEM_CD_BUT_TOO_SHORT))
#define PROB_HDR_NOT_CANONICAL(f) ((f.problems) & (PROBLEM_HEADER_NOT_CANONICAL))
#define PROB_EXTRA_CHUNKS(f) ((f.problems) & (PROBLEM_EXTRA_CHUNKS))
#define PROB_HDR_INCONSISTENT(f) ((f.problems) & (PROBLEM_HEADER_INCONSISTENT))
#ifndef _SHN_CONFIG
#define _SHN_CONFIG
typedef struct _shn_config
{
int error_output_method;
char *seek_tables_path;
char *relative_seek_tables_path;
int verbose;
int swap_bytes;
} shn_config;
#endif
typedef struct _shn_decode_state
{
uchar *getbuf;
uchar *getbufp;
int nbitget;
int nbyteget;
ulong gbuffer;
schar *writebuf;
schar *writefub;
int nwritebuf;
} shn_decode_state;
typedef struct _shn_seek_header
{
uchar data[SEEK_HEADER_SIZE];
slong version;
ulong shnFileSize;
} shn_seek_header;
typedef struct _shn_seek_trailer
{
uchar data[SEEK_TRAILER_SIZE];
ulong seekTableSize;
} shn_seek_trailer;
typedef struct _shn_seek_entry
{
uchar data[SEEK_ENTRY_SIZE];
} shn_seek_entry;
/* old way, kept for reference.
(changed because some compilers apparently don't support #pragma pack(1))
typedef struct _shn_seek_header
{
char signature[4];
unsigned long version;
unsigned long shnFileSize;
} shn_seek_header;
typedef struct _shn_seek_trailer
{
unsigned long seekTableSize;
char signature[8];
} shn_seek_trailer;
typedef struct _shn_seek_entry
{
unsigned long shnSample;
unsigned long shnByteOffset;
unsigned long shnLastPosition;
unsigned short shnByteGet;
unsigned short shnBufferOffset;
unsigned short shnBitOffset;
unsigned long shnGBuffer;
unsigned short shnBitShift;
long cbuf0[3];
long cbuf1[3];
long offset0[4];
long offset1[4];
} shn_seek_entry;
*/
typedef struct _shn_wave_header
{
char *filename,
m_ss[16];
uint header_size;
ushort channels,
block_align,
bits_per_sample,
wave_format;
ulong samples_per_sec,
avg_bytes_per_sec,
rate,
length,
data_size,
total_size,
chunk_size,
actual_size;
double exact_length;
int file_has_id3v2_tag;
long id3v2_tag_size;
ulong problems;
} shn_wave_header;
typedef struct _shn_vars
{
FILE *fd;
int seek_to;
int eof;
int going;
slong seek_table_entries;
ulong seek_resolution;
int bytes_in_buf;
uchar buffer[OUT_BUFFER_SIZE];
int bytes_in_header;
uchar header[OUT_BUFFER_SIZE];
int fatal_error;
schar fatal_error_msg[BUF_SIZE];
int reading_function_code;
ulong last_file_position;
ulong last_file_position_no_really;
ulong initial_file_position;
ulong bytes_read;
unsigned short bitshift;
long seek_offset;
} shn_vars;
typedef struct _shn_file
{
shn_vars vars;
shn_decode_state *decode_state;
shn_wave_header wave_header;
shn_seek_header seek_header;
shn_seek_trailer seek_trailer;
shn_seek_entry *seek_table;
shn_config config;
} shn_file;
extern shn_seek_entry *shn_seek_entry_search(shn_config,shn_seek_entry *,ulong,ulong,ulong,ulong);
extern void shn_load_seek_table(shn_file *,char *);
extern void shn_unload(shn_file *);
extern void shn_display_about(void);
extern void shn_display_configure(void);
extern void shn_display_info(shn_file *);
extern int shn_verify_header(shn_file *);
extern int shn_filename_contains_a_dot(char *);
extern char *shn_get_base_filename(char *);
extern char *shn_get_base_directory(char *);
extern void shn_length_to_str(shn_file *);
extern ulong shn_uchar_to_ulong_le(uchar *);
extern slong shn_uchar_to_slong_le(uchar *);
extern ushort shn_uchar_to_ushort_le(uchar *);
extern char *shn_format_to_str(ushort);
extern void shn_debug(shn_config,char *, ...);
extern void shn_error(shn_config,char *, ...);
extern void shn_error_fatal(shn_file *,char *, ...);
extern void shn_snprintf(char *,int,char *, ...);
extern FILE *shn_open_and_discard_id3v2_tag(char *,int *,long *);
#endif

View file

@ -0,0 +1,220 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#ifndef _SHORTEN_H
#define _SHORTEN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <pthread.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#else
# if SIZEOF_UNSIGNED_LONG == 4
# define uint32_t unsigned long
# define int32_t long
# else
# define uint32_t unsigned int
# define int32_t int
# endif
# define uint16_t unsigned short
# define uint8_t unsigned char
# define int16_t short
# define int8_t char
#endif
#undef ulong
#undef ushort
#undef uchar
#undef slong
#undef sshort
#undef schar
#define ulong uint32_t
#define ushort uint16_t
#define uchar uint8_t
#define slong int32_t
#define sshort int16_t
#define schar int8_t
#include "shn.h"
#define MAGIC "ajkg"
#define FORMAT_VERSION 2
#define MIN_SUPPORTED_VERSION 1
#define MAX_SUPPORTED_VERSION 3
#define MAX_VERSION 7
#define UNDEFINED_UINT -1
#define DEFAULT_BLOCK_SIZE 256
#define DEFAULT_V0NMEAN 0
#define DEFAULT_V2NMEAN 4
#define DEFAULT_MAXNLPC 0
#define DEFAULT_NCHAN 1
#define DEFAULT_NSKIP 0
#define DEFAULT_NDISCARD 0
#define NBITPERLONG 32
#define DEFAULT_MINSNR 256
#define DEFAULT_MAXRESNSTR "32.0"
#define DEFAULT_QUANTERROR 0
#define MINBITRATE 2.5
#define MAX_LPC_ORDER 64
#define CHANSIZE 0
#define ENERGYSIZE 3
#define BITSHIFTSIZE 2
#define NWRAP 3
#define FNSIZE 2
#define FN_DIFF0 0
#define FN_DIFF1 1
#define FN_DIFF2 2
#define FN_DIFF3 3
#define FN_QUIT 4
#define FN_BLOCKSIZE 5
#define FN_BITSHIFT 6
#define FN_QLPC 7
#define FN_ZERO 8
#define FN_VERBATIM 9
#define VERBATIM_CKSIZE_SIZE 5 /* a var_put code size */
#define VERBATIM_BYTE_SIZE 8 /* code size 8 on single bytes means
* no compression at all */
#define VERBATIM_CHUNK_MAX 256 /* max. size of a FN_VERBATIM chunk */
#define ULONGSIZE 2
#define NSKIPSIZE 1
#define LPCQSIZE 2
#define LPCQUANT 5
#define XBYTESIZE 7
#define TYPESIZE 4
#define TYPE_AU1 0 /* original lossless ulaw */
#define TYPE_S8 1 /* signed 8 bit characters */
#define TYPE_U8 2 /* unsigned 8 bit characters */
#define TYPE_S16HL 3 /* signed 16 bit shorts: high-low */
#define TYPE_U16HL 4 /* unsigned 16 bit shorts: high-low */
#define TYPE_S16LH 5 /* signed 16 bit shorts: low-high */
#define TYPE_U16LH 6 /* unsigned 16 bit shorts: low-high */
#define TYPE_ULAW 7 /* lossy ulaw: internal conversion to linear */
#define TYPE_AU2 8 /* new ulaw with zero mapping */
#define TYPE_AU3 9 /* lossless alaw */
#define TYPE_ALAW 10 /* lossy alaw: internal conversion to linear */
#define TYPE_RIFF_WAVE 11 /* Microsoft .WAV files */
#define TYPE_EOF 12
#define TYPE_GENERIC_ULAW 128
#define TYPE_GENERIC_ALAW 129
#define POSITIVE_ULAW_ZERO 0xff
#define NEGATIVE_ULAW_ZERO 0x7f
#ifndef MAX_PATH
#define MAX_PATH 2048
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#if defined(unix) && !defined(linux)
#define labs abs
#endif
#define ROUNDEDSHIFTDOWN(x, n) (((n) == 0) ? (x) : ((x) >> ((n) - 1)) >> 1)
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* BUFSIZ must be a multiple of four to contain a whole number of words */
#ifdef BUFSIZ
#undef BUFSIZ
#endif
#define BUFSIZ 512
#define V2LPCQOFFSET (1 << LPCQUANT);
#define UINT_GET(nbit, file) \
((version == 0) ? uvar_get(nbit, file) : ulong_get(file))
#define putc_exit(val, stream)\
{ char rval;\
if((rval = putc((val), (stream))) != (char) (val))\
complain("FATALERROR: write failed: putc returns EOF");\
}
extern int getc_exit_val;
#define getc_exit(stream)\
(((getc_exit_val = getc(stream)) == EOF) ? \
complain("FATALERROR: read failed: getc returns EOF"), 0: getc_exit_val)
/************************/
/* defined in shorten.c */
extern void init_offset(slong**, int, int, int);
extern int shorten(FILE*, FILE*, int, char**);
/**************************/
/* defined in Sulawalaw.c */
extern int Sulaw2lineartab[];
#define Sulaw2linear(i) (Sulaw2lineartab[i])
#ifndef Sulaw2linear
extern int Sulaw2linear(uchar);
#endif
extern uchar Slinear2ulaw(int);
extern int Salaw2lineartab[];
#define Salaw2linear(i) (Salaw2lineartab[i])
#ifndef Salaw2linear
extern int Salaw2linear(uchar);
#endif
extern uchar Slinear2alaw(int);
/**********************/
/* defined in fixio.c */
extern void init_sizeof_sample(void);
extern void fwrite_type_init(shn_file*);
extern void fwrite_type(slong**,int,int,int,shn_file*);
extern void fwrite_type_quit(shn_file*);
extern void fix_bitshift(slong*, int, int, int);
/**********************/
/* defined in vario.c */
extern void var_get_init(shn_file*);
extern slong uvar_get(int, shn_file*);
extern slong var_get(int, shn_file*);
extern ulong ulong_get(shn_file*);
extern void var_get_quit(shn_file*);
extern int sizeof_uvar(ulong, int);
extern int sizeof_var(slong, int);
extern void mkmasktab(void);
extern ulong word_get(shn_file*);
/**********************/
/* defined in array.c */
extern void* pmalloc(ulong, shn_file*);
extern slong** long2d(ulong, ulong, shn_file*);
#endif

View file

@ -0,0 +1,21 @@
noinst_LTLIBRARIES = libshorten.la
BUILT_SOURCES = bitshift.h
libshorten_la_LDFLAGS = -module -export-dynamic -avoid-version
libshorten_la_SOURCES = array.c convert.c fixio.c id3v2.c misc.c output.c shorten.c seek.c sulawalaw.c vario.c wave.c decode.c
INCLUDES = -I$(top_srcdir)/include
CLEANFILES = $(BUILT_SOURCES)
array.c: $(BUILT_SOURCES)
bitshift.h:
-@if [ -x "../util/mkbshift" ] ; then \
../util/mkbshift ; \
else \
echo "" ; \
echo "*** missing ../util/mkbshift - run '$(MAKE)' in the top-level directory to build it ***" ; \
echo "" ; \
exit 1 ; \
fi

View file

@ -0,0 +1,40 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include "shorten.h"
void *pmalloc(ulong size, shn_file *this_shn) {
void *ptr;
ptr = malloc(size);
if(ptr == NULL)
shn_error_fatal(this_shn,"Call to malloc(%ld) failed in pmalloc() -\nyour system may be low on memory", size);
return(ptr);
}
slong **long2d(ulong n0, ulong n1, shn_file *this_shn) {
slong **array0 = NULL;
if((array0 = (slong**) pmalloc((ulong) (n0 * sizeof(slong*) +
n0 * n1 * sizeof(slong)),this_shn)) != NULL ) {
slong *array1 = (slong*) (array0 + n0);
int i;
for(i = 0; i < n0; i++)
array0[i] = array1 + i * n1;
}
return(array0);
}

View file

@ -0,0 +1,42 @@
/* convert.c - functions to convert little-endian data to endian of host
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#include <stdlib.h>
#include "shorten.h"
ulong shn_uchar_to_ulong_le(uchar *buf)
/* converts 4 bytes stored in little-endian format to a ulong */
{
return (ulong)((buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]);
}
slong shn_uchar_to_slong_le(uchar *buf)
/* converts 4 bytes stored in little-endian format to an slong */
{
return (slong)shn_uchar_to_ulong_le(buf);
}
ushort shn_uchar_to_ushort_le(uchar *buf)
/* converts 4 bytes stored in little-endian format to a ushort */
{
return (ushort)((buf[1] << 8) + buf[0]);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,276 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "shorten.h"
#include "bitshift.h"
#define CAPMAXSCHAR(x) ((x > 127) ? 127 : x)
#define CAPMAXUCHAR(x) ((x > 255) ? 255 : x)
#define CAPMAXSHORT(x) ((x > 32767) ? 32767 : x)
#define CAPMAXUSHORT(x) ((x > 65535) ? 65535 : x)
static int sizeof_sample[TYPE_EOF];
void init_sizeof_sample() {
sizeof_sample[TYPE_AU1] = sizeof(uchar);
sizeof_sample[TYPE_S8] = sizeof(schar);
sizeof_sample[TYPE_U8] = sizeof(uchar);
sizeof_sample[TYPE_S16HL] = sizeof(ushort);
sizeof_sample[TYPE_U16HL] = sizeof(ushort);
sizeof_sample[TYPE_S16LH] = sizeof(ushort);
sizeof_sample[TYPE_U16LH] = sizeof(ushort);
sizeof_sample[TYPE_ULAW] = sizeof(uchar);
sizeof_sample[TYPE_AU2] = sizeof(uchar);
sizeof_sample[TYPE_AU3] = sizeof(uchar);
sizeof_sample[TYPE_ALAW] = sizeof(uchar);
}
/***************/
/* fixed write */
/***************/
void fwrite_type_init(shn_file *this_shn) {
init_sizeof_sample();
this_shn->decode_state->writebuf = (schar*) NULL;
this_shn->decode_state->writefub = (schar*) NULL;
this_shn->decode_state->nwritebuf = 0;
}
void fwrite_type_quit(shn_file *this_shn) {
if(this_shn->decode_state->writebuf != NULL) {
free(this_shn->decode_state->writebuf);
this_shn->decode_state->writebuf = NULL;
}
if(this_shn->decode_state->writefub != NULL) {
free(this_shn->decode_state->writefub);
this_shn->decode_state->writefub = NULL;
}
}
/* convert from signed ints to a given type and write */
void fwrite_type(slong **data,int ftype,int nchan,int nitem,shn_file *this_shn)
{
int hiloint = 1, hilo = !(*((char*) &hiloint));
int i, nwrite = 0, datasize = sizeof_sample[ftype], chan;
slong *data0 = data[0];
int bufAvailable = OUT_BUFFER_SIZE - this_shn->vars.bytes_in_buf;
if(this_shn->decode_state->nwritebuf < nchan * nitem * datasize) {
this_shn->decode_state->nwritebuf = nchan * nitem * datasize;
if(this_shn->decode_state->writebuf != NULL) free(this_shn->decode_state->writebuf);
if(this_shn->decode_state->writefub != NULL) free(this_shn->decode_state->writefub);
this_shn->decode_state->writebuf = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn);
if (!this_shn->decode_state->writebuf)
return;
this_shn->decode_state->writefub = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn);
if (!this_shn->decode_state->writefub)
return;
}
switch(ftype) {
case TYPE_AU1: /* leave the conversion to fix_bitshift() */
case TYPE_AU2: {
uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = data0[i];
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = data[chan][i];
break;
}
case TYPE_U8: {
uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = CAPMAXUCHAR(data0[i]);
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = CAPMAXUCHAR(data[chan][i]);
break;
}
case TYPE_S8: {
schar *writebufp = (schar*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = CAPMAXSCHAR(data0[i]);
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = CAPMAXSCHAR(data[chan][i]);
break;
}
case TYPE_S16HL:
case TYPE_S16LH: {
short *writebufp = (short*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = CAPMAXSHORT(data0[i]);
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = CAPMAXSHORT(data[chan][i]);
break;
}
case TYPE_U16HL:
case TYPE_U16LH: {
ushort *writebufp = (ushort*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = CAPMAXUSHORT(data0[i]);
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = CAPMAXUSHORT(data[chan][i]);
break;
}
case TYPE_ULAW: {
uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = Slinear2ulaw(CAPMAXSHORT((data0[i] << 3)));
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = Slinear2ulaw(CAPMAXSHORT((data[chan][i] << 3)));
break;
}
case TYPE_AU3: {
uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
if(data0[i] < 0)
*writebufp++ = (127 - data0[i]) ^ 0xd5;
else
*writebufp++ = (data0[i] + 128) ^ 0x55;
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
if(data[chan][i] < 0)
*writebufp++ = (127 - data[chan][i]) ^ 0xd5;
else
*writebufp++ = (data[chan][i] + 128) ^ 0x55;
break;
}
case TYPE_ALAW: {
uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
if(nchan == 1)
for(i = 0; i < nitem; i++)
*writebufp++ = Slinear2alaw(CAPMAXSHORT((data0[i] << 3)));
else
for(i = 0; i < nitem; i++)
for(chan = 0; chan < nchan; chan++)
*writebufp++ = Slinear2alaw(CAPMAXSHORT((data[chan][i] << 3)));
break;
}
}
switch(ftype) {
case TYPE_AU1:
case TYPE_S8:
case TYPE_U8:
case TYPE_ULAW:
case TYPE_AU2:
case TYPE_AU3:
case TYPE_ALAW:
if (datasize*nchan*nitem <= bufAvailable) {
memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem);
this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
nwrite = nitem;
}
else
shn_debug(this_shn->config, "Buffer overrun in fwrite_type() [case 1]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
break;
case TYPE_S16HL:
case TYPE_U16HL:
if(hilo)
{
if (datasize*nchan*nitem <= bufAvailable) {
memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem);
this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
nwrite = nitem;
}
else
shn_debug(this_shn->config, "Buffer overrun in fwrite_type() [case 2]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
}
else
{
swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem);
if (datasize*nchan*nitem <= bufAvailable) {
memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem);
this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
nwrite = nitem;
}
else
shn_debug(this_shn->config, "Buffer overrun in fwrite_type() [case 3]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
}
break;
case TYPE_S16LH:
case TYPE_U16LH:
if(hilo)
{
swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem);
if (datasize*nchan*nitem <= bufAvailable) {
memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem);
this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
nwrite = nitem;
}
else
shn_debug(this_shn->config, "Buffer overrun in fwrite_type() [case 4]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
}
else
{
if (datasize*nchan*nitem <= bufAvailable) {
memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem);
this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
nwrite = nitem;
}
else
shn_debug(this_shn->config, "Buffer overrun in fwrite_type() [case 5]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
}
break;
}
if(nwrite != nitem)
shn_error_fatal(this_shn,"Failed to write decompressed stream -\npossible corrupt or truncated file");
}
/*************/
/* bitshifts */
/*************/
void fix_bitshift(buffer, nitem, bitshift, ftype) slong *buffer; int nitem,
bitshift, ftype; {
int i;
if(ftype == TYPE_AU1)
for(i = 0; i < nitem; i++)
buffer[i] = ulaw_outward[bitshift][buffer[i] + 128];
else if(ftype == TYPE_AU2)
for(i = 0; i < nitem; i++) {
if(buffer[i] >= 0)
buffer[i] = ulaw_outward[bitshift][buffer[i] + 128];
else if(buffer[i] == -1)
buffer[i] = NEGATIVE_ULAW_ZERO;
else
buffer[i] = ulaw_outward[bitshift][buffer[i] + 129];
}
else
if(bitshift != 0)
for(i = 0; i < nitem; i++)
buffer[i] <<= bitshift;
}

View file

@ -0,0 +1,120 @@
/* id3v2.c - functions to handle ID3v2 tags prepended to shn files
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#include <stdio.h>
#include "shorten.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define ID3V2_MAGIC "ID3"
typedef struct {
char magic[3];
unsigned char version[2];
unsigned char flags[1];
unsigned char size[4];
} _id3v2_header;
int tagcmp(char *got,char *expected)
/* compare got against expected, up to the length of expected */
{
int i;
for (i=0;*(expected+i);i++) {
if (*(got+i) != *(expected+i))
return i+1;
}
return 0;
}
unsigned long synchsafe_int_to_ulong(unsigned char *buf)
/* converts 4 bytes stored in synchsafe integer format to an unsigned long */
{
return (unsigned long)(((buf[0] & 0x7f) << 21) | ((buf[1] & 0x7f) << 14) | ((buf[2] & 0x7f) << 7) | (buf[3] & 0x7f));
}
static unsigned long check_for_id3v2_tag(FILE *f)
{
_id3v2_header id3v2_header;
unsigned long tag_size;
/* read an ID3v2 header's size worth of data */
if (sizeof(_id3v2_header) != fread(&id3v2_header,1,sizeof(_id3v2_header),f)) {
return 0;
}
/* verify this is an ID3v2 header */
if (tagcmp(id3v2_header.magic,ID3V2_MAGIC) ||
0xff == id3v2_header.version[0] || 0xff == id3v2_header.version[1] ||
0x80 <= id3v2_header.size[0] || 0x80 <= id3v2_header.size[1] ||
0x80 <= id3v2_header.size[2] || 0x80 <= id3v2_header.size[3])
{
return 0;
}
/* calculate and return ID3v2 tag size */
tag_size = synchsafe_int_to_ulong(id3v2_header.size);
return tag_size;
}
FILE *shn_open_and_discard_id3v2_tag(char *filename,int *file_has_id3v2_tag,long *id3v2_tag_size)
/* opens a file, and if it contains an ID3v2 tag, skips past it */
{
FILE *f;
unsigned long tag_size;
if (NULL == (f = fopen(filename,"rb"))) {
return NULL;
}
if (file_has_id3v2_tag)
*file_has_id3v2_tag = 0;
if (id3v2_tag_size)
*id3v2_tag_size = 0;
/* check for ID3v2 tag on input */
if (0 == (tag_size = check_for_id3v2_tag(f))) {
fclose(f);
return fopen(filename,"rb");
}
if (file_has_id3v2_tag)
*file_has_id3v2_tag = 2;
if (id3v2_tag_size)
*id3v2_tag_size = (long)(tag_size + sizeof(_id3v2_header));
fprintf(stderr, "Discarding %lu-byte ID3v2 tag at beginning of file '%s'.",tag_size+sizeof(_id3v2_header),filename);
if (0 != fseek(f,(long)tag_size,SEEK_CUR)) {
fprintf(stderr, "Error while discarding ID3v2 tag in file '%s'.",filename);
fclose(f);
return fopen(filename,"rb");
}
return f;
}

View file

@ -0,0 +1,149 @@
/* misc.c - miscellaneous functions
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "shorten.h"
void shn_snprintf(char *dest,int maxlen,char *formatstr, ...)
/* acts like snprintf, but makes 100% sure the string is NULL-terminated */
{
va_list args;
va_start(args,formatstr);
shn_vsnprintf(dest,maxlen,formatstr,args);
dest[maxlen-1] = 0;
va_end(args);
}
int shn_filename_contains_a_dot(char *filename)
{
char *slash,*dot;
dot = strrchr(filename,'.');
if (!dot)
return 0;
slash = strrchr(filename,'/');
if (!slash)
return 1;
if (slash < dot)
return 1;
else
return 0;
}
char *shn_get_base_filename(char *filename)
{
char *b,*e,*p,*base;
b = strrchr(filename,'/');
if (b)
b++;
else
b = filename;
e = strrchr(filename,'.');
if (e < b)
e = filename + strlen(filename);
if (NULL == (base = malloc((e - b + 1) * sizeof(char))))
{
fprintf(stderr, "Could not allocate memory for base filename");
return NULL;
}
for (p=b;p<e;p++)
*(base + (p - b)) = *p;
*(base + (p - b)) = '\0';
return base;
}
char *shn_get_base_directory(char *filename)
{
char *e,*p,*base;
e = strrchr(filename,'/');
if (!e)
e = filename;
if (NULL == (base = malloc((e - filename + 1) * sizeof(char))))
{
fprintf(stderr, "Could not allocate memory for base directory");
return NULL;
}
for (p=filename;p<e;p++)
*(base + (p - filename)) = *p;
*(base + (p - filename)) = '\0';
return base;
}
void shn_length_to_str(shn_file *info)
/* converts length of file to a string in m:ss or m:ss.ff format */
{
ulong newlength,rem1,rem2,frames,ms;
double tmp;
if (PROB_NOT_CD(info->wave_header)) {
newlength = (ulong)info->wave_header.exact_length;
tmp = info->wave_header.exact_length - (double)((ulong)info->wave_header.exact_length);
ms = (ulong)((tmp * 1000.0) + 0.5);
if (1000 == ms) {
ms = 0;
newlength++;
}
shn_snprintf(info->wave_header.m_ss,16,"%lu:%02lu.%03lu",newlength/60,newlength%60,ms);
}
else {
newlength = info->wave_header.length;
rem1 = info->wave_header.data_size % CD_RATE;
rem2 = rem1 % CD_BLOCK_SIZE;
frames = rem1 / CD_BLOCK_SIZE;
if (rem2 >= (CD_BLOCK_SIZE / 2))
frames++;
if (frames == CD_BLOCKS_PER_SEC) {
frames = 0;
newlength++;
}
shn_snprintf(info->wave_header.m_ss,16,"%lu:%02lu.%02lu",newlength/60,newlength%60,frames);
}
}

View file

@ -0,0 +1,99 @@
/* output.c - functions for message and error output
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "shorten.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
void print_lines(char *prefix,char *message)
{
char *head, *tail;
head = tail = message;
while (*head != '\0') {
if (*head == '\n') {
*head = '\0';
fprintf(stderr,"%s%s\n",prefix,tail);
tail = head + 1;
}
head++;
}
fprintf(stderr,"%s%s\n",prefix,tail);
}
void shn_error(shn_config config, char *msg, ...)
{
va_list args;
char msgbuf[BUF_SIZE];
va_start(args,msg);
shn_vsnprintf(msgbuf,BUF_SIZE,msg,args);
switch (config.error_output_method) {
case ERROR_OUTPUT_STDERR:
print_lines(PACKAGE ": ",msgbuf);
break;
default:
if (0 != config.verbose)
print_lines(PACKAGE " [error]: ",msgbuf);
}
va_end(args);
}
void shn_debug(shn_config config, char *msg, ...)
{
va_list args;
char msgbuf[BUF_SIZE];
va_start(args,msg);
shn_vsnprintf(msgbuf,BUF_SIZE,msg,args);
if (0 != config.verbose)
print_lines(PACKAGE " [debug]: ",msgbuf);
va_end(args);
}
void shn_error_fatal(shn_file *this_shn,char *complaint, ...)
{
va_list args;
va_start(args,complaint);
if (NULL != this_shn) {
if (0 == this_shn->vars.fatal_error) {
this_shn->vars.fatal_error = 1;
this_shn->vars.going = 0;
shn_vsnprintf(this_shn->vars.fatal_error_msg,BUF_SIZE,complaint,args);
}
}
va_end(args);
}

View file

@ -0,0 +1,284 @@
/* seek.c - functions related to real-time seeking
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#include <stdlib.h>
#include "shorten.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define ID3V1_TAG_SIZE 128
shn_seek_entry *shn_seek_entry_search(shn_config config, shn_seek_entry *table,ulong goal,ulong min,ulong max,ulong resolution)
{
ulong med = (min + max) / 2;
shn_seek_entry *middle = table + med;
ulong sample = shn_uchar_to_ulong_le(middle->data);
shn_debug(config, "Examining seek table entry %lu with sample %lu (min/max = %lu/%lu, goal sample is %lu, resolution is %lu samples)",med,sample,min,max,goal,resolution);
if (goal < sample)
return shn_seek_entry_search(config, table,goal,min,med-1,resolution);
if (goal > sample + resolution)
return shn_seek_entry_search(config, table,goal,med+1,max,resolution);
return middle;
}
int load_separate_seek_table_generic(char *filename,shn_file *this_shn)
{
FILE *f;
slong seek_table_len;
shn_debug(this_shn->config, "Looking for seek table in separate file: '%s'",filename);
if (!(f=fopen(filename,"rb")))
{
return 0;
}
fseek(f,0,SEEK_END);
seek_table_len = (slong)ftell(f) - SEEK_HEADER_SIZE;
fseek(f,0,SEEK_SET);
if (fread((void *)this_shn->seek_header.data,1,SEEK_HEADER_SIZE,f) == SEEK_HEADER_SIZE)
{
this_shn->seek_header.version = (slong)shn_uchar_to_ulong_le(this_shn->seek_header.data+4);
this_shn->seek_header.shnFileSize = shn_uchar_to_ulong_le(this_shn->seek_header.data+8);
if (memcmp(this_shn->seek_header.data,SEEK_HEADER_SIGNATURE,strlen(SEEK_HEADER_SIGNATURE)) == 0)
{
if (this_shn->seek_header.shnFileSize != this_shn->wave_header.actual_size)
{
shn_debug(this_shn->config, "warning: Seek table expected .shn file size %lu differs from actual .shn file size %lu - seek table might not belong to this file",
this_shn->seek_header.shnFileSize,this_shn->wave_header.actual_size);
}
if ((this_shn->seek_table = malloc(seek_table_len)))
{
if (fread((void *)this_shn->seek_table,1,seek_table_len,f) == seek_table_len)
{
shn_debug(this_shn->config, "Successfully loaded seek table in separate file: '%s'",filename);
this_shn->vars.seek_table_entries = seek_table_len / SEEK_ENTRY_SIZE;
if (this_shn->vars.seek_table_entries > 1)
this_shn->vars.seek_resolution = shn_uchar_to_ulong_le(this_shn->seek_table->data+SEEK_ENTRY_SIZE);
else
this_shn->vars.seek_resolution = SEEK_RESOLUTION;
fclose(f);
return 1;
}
}
}
}
fclose(f);
return 0;
}
int load_appended_seek_table(shn_file *this_shn,char *filename,long bytes_from_end)
{
switch (bytes_from_end)
{
case 0:
shn_debug(this_shn->config, "Looking for seek table appended to file: '%s'",filename);
break;
case ID3V1_TAG_SIZE:
shn_debug(this_shn->config, "Looking for seek table hidden behind an ID3v1 tag at the end of file: '%s'",filename);
break;
default:
shn_debug(this_shn->config, "Looking for seek table located %ld bytes from the end of file: '%s'",bytes_from_end,filename);
break;
}
fseek(this_shn->vars.fd,-(SEEK_TRAILER_SIZE+bytes_from_end),SEEK_END);
if (fread((void *)this_shn->seek_trailer.data,1,SEEK_TRAILER_SIZE,this_shn->vars.fd) == SEEK_TRAILER_SIZE)
{
this_shn->seek_trailer.seekTableSize = shn_uchar_to_ulong_le(this_shn->seek_trailer.data);
if (memcmp(this_shn->seek_trailer.data+4,SEEK_TRAILER_SIGNATURE,strlen(SEEK_TRAILER_SIGNATURE)) == 0)
{
fseek(this_shn->vars.fd,-(this_shn->seek_trailer.seekTableSize+bytes_from_end),SEEK_END);
this_shn->seek_trailer.seekTableSize -= (SEEK_HEADER_SIZE + SEEK_TRAILER_SIZE);
if (fread((void *)this_shn->seek_header.data,1,SEEK_HEADER_SIZE,this_shn->vars.fd) == SEEK_HEADER_SIZE)
{
this_shn->seek_header.version = (slong)shn_uchar_to_ulong_le(this_shn->seek_header.data+4);
this_shn->seek_header.shnFileSize = shn_uchar_to_ulong_le(this_shn->seek_header.data+8);
if ((this_shn->seek_table = malloc(this_shn->seek_trailer.seekTableSize)))
{
if (fread((void *)this_shn->seek_table,1,this_shn->seek_trailer.seekTableSize,this_shn->vars.fd) == this_shn->seek_trailer.seekTableSize)
{
shn_debug(this_shn->config, "Successfully loaded seek table appended to file: '%s'",filename);
this_shn->vars.seek_table_entries = this_shn->seek_trailer.seekTableSize / SEEK_ENTRY_SIZE;
if (this_shn->vars.seek_table_entries > 1)
this_shn->vars.seek_resolution = shn_uchar_to_ulong_le(this_shn->seek_table->data+SEEK_ENTRY_SIZE);
else
this_shn->vars.seek_resolution = SEEK_RESOLUTION;
return 1;
}
}
}
}
}
return 0;
}
int load_separate_seek_table_samedir(shn_file *this_shn,char *filename)
{
char *altfilename,*basefile,*basedir;
if (!(basefile = shn_get_base_filename(filename)))
{
return 0;
}
if (!(basedir = shn_get_base_directory(filename)))
{
free(basefile);
return 0;
}
if (!(altfilename = malloc(strlen(basedir)+strlen(basefile)+sizeof(SEEK_SUFFIX)+3)))
{
shn_debug(this_shn->config, "Could not allocate memory for same dir filename");
free(basefile);
free(basedir);
return 0;
}
sprintf(altfilename,"%s/%s.%s",basedir,basefile,SEEK_SUFFIX);
free(basefile);
free(basedir);
if (load_separate_seek_table_generic(altfilename,this_shn))
{
free(altfilename);
return 1;
}
free(altfilename);
return 0;
}
int load_separate_seek_table_relative(shn_file *this_shn,char *filename)
{
char *altfilename,*basefile,*basedir;
/* Checking if this_shn->config.relative_seek_tables_path is NULL */
if(!(this_shn->config.relative_seek_tables_path))
this_shn->config.relative_seek_tables_path = "";
if (0 == strcmp(this_shn->config.relative_seek_tables_path,""))
return 0;
if (!(basefile = shn_get_base_filename(filename)))
{
return 0;
}
if (!(basedir = shn_get_base_directory(filename)))
{
free(basefile);
return 0;
}
if (!(altfilename = malloc(strlen(basedir)+strlen(this_shn->config.relative_seek_tables_path)+strlen(basefile)+sizeof(SEEK_SUFFIX)+4)))
{
shn_debug(this_shn->config, "Could not allocate memory for absolute filename");
free(basefile);
free(basedir);
return 0;
}
sprintf(altfilename,"%s/%s/%s.%s",basedir,this_shn->config.relative_seek_tables_path,basefile,SEEK_SUFFIX);
free(basefile);
free(basedir);
if (load_separate_seek_table_generic(altfilename,this_shn))
{
free(altfilename);
return 1;
}
free(altfilename);
return 0;
}
int load_separate_seek_table_absolute(shn_file *this_shn,char *filename)
{
char *altfilename,*basefile;
/* Checking this_shn->config.seek_tables_path */
if(!(this_shn->config.seek_tables_path))
this_shn->config.seek_tables_path = "";
if (!(basefile = shn_get_base_filename(filename)))
{
return 0;
}
if (!(altfilename = malloc(strlen(this_shn->config.seek_tables_path)+strlen(basefile)+sizeof(SEEK_SUFFIX)+3)))
{
shn_debug(this_shn->config, "Could not allocate memory for same dir filename");
free(basefile);
return 0;
}
sprintf(altfilename,"%s/%s.%s",this_shn->config.seek_tables_path,basefile,SEEK_SUFFIX);
free(basefile);
if (load_separate_seek_table_generic(altfilename,this_shn))
{
free(altfilename);
return 1;
}
free(altfilename);
return 0;
}
void shn_load_seek_table(shn_file *this_shn,char *filename)
{
if (load_appended_seek_table(this_shn,filename,0))
return;
if (load_appended_seek_table(this_shn,filename,ID3V1_TAG_SIZE))
return;
if (load_separate_seek_table_samedir(this_shn,filename))
return;
if (load_separate_seek_table_relative(this_shn,filename))
return;
if (load_separate_seek_table_absolute(this_shn,filename))
return;
shn_debug(this_shn->config, "Could not find any seek tables");
}

View file

@ -0,0 +1,54 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <setjmp.h>
#include "shorten.h"
void init_offset(slong **offset,int nchan,int nblock,int ftype)
{
slong mean = 0;
int chan, i;
/* initialise offset */
switch(ftype)
{
case TYPE_AU1:
case TYPE_S8:
case TYPE_S16HL:
case TYPE_S16LH:
case TYPE_ULAW:
case TYPE_AU2:
case TYPE_AU3:
case TYPE_ALAW:
mean = 0;
break;
case TYPE_U8:
mean = 0x80;
break;
case TYPE_U16HL:
case TYPE_U16LH:
mean = 0x8000;
break;
default:
fprintf(stderr, "Unknown file type: %d", ftype);
}
for(chan = 0; chan < nchan; chan++)
for(i = 0; i < nblock; i++)
offset[chan][i] = mean;
}

View file

@ -0,0 +1,192 @@
/*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#include "shorten.h"
int Sulaw2lineartab[] = {-32124, -31100, -30076, -29052, -28028, -27004,
-25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812,
-17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436,
-12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828,
-8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884,
-5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644,
-3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364,
-2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500,
-1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876,
-844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524,
-492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276,
-260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112,
-104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0,
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908,
21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460,
13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340,
8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884,
5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516,
3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108,
1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308,
1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684,
652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308,
292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104,
96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0};
#ifndef Sulaw2linear
#ifdef __STDC__
int Sulaw2linear(uchar ulaw) {
#else
int Sulaw2linear(ulaw) uchar ulaw; {
#endif
return(Sulaw2lineartab[ulaw]);
}
#endif
/* adapted by ajr for int input */
#ifdef __STDC__
uchar Slinear2ulaw(int sample) {
#else
uchar Slinear2ulaw(sample) int sample; {
#endif
/*
** This routine converts from linear to ulaw.
**
** Craig Reese: IDA/Supercomputing Research Center
** Joe Campbell: Department of Defense
** 29 September 1989
**
** References:
** 1) CCITT Recommendation G.711 (very difficult to follow)
** 2) "A New Digital Technique for Implementation of Any
** Continuous PCM Companding Law," Villeret, Michel,
** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
** 1973, pg. 11.12-11.17
** 3) MIL-STD-188-113,"Interoperability and Performance Standards
** for Analog-to_Digital Conversion Techniques,"
** 17 February 1987
**
** Input: Signed 16 bit linear sample
** Output: 8 bit ulaw sample
*/
#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
#define CLIP 32635
static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
int sign, exponent, mantissa;
uchar ulawbyte;
/* Get the sample into sign-magnitude. */
if(sample < 0) {
sign = 0x80;
sample = -sample;
}
else
sign = 0;
/* clip the magnitude */
if(sample > CLIP) sample = CLIP;
/* Convert from 16 bit linear to ulaw. */
sample = sample + BIAS;
exponent = exp_lut[( sample >> 7 ) & 0xFF];
mantissa = (sample >> (exponent + 3)) & 0x0F;
ulawbyte = ~(sign | (exponent << 4) | mantissa);
return(ulawbyte);
}
/******************
* ALAW starts here
*/
int Salaw2lineartab[] = {-5504, -5248, -6016, -5760, -4480, -4224,
-4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648,
-4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064,
-23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256,
-31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032,
-11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616,
-13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264,
-312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72,
-120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136,
-184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656,
-752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816,
-784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008,
2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136,
3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496,
12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616,
13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296,
472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56,
40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440,
1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760,
1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976,
816, 784, 880, 848};
#ifndef Salaw2linear
#ifdef __STDC__
int Salaw2linear(uchar alaw) {
#else
int Salaw2linear(alaw) uchar alaw; {
#endif
return(Salaw2lineartab[alaw]);
}
#endif
/* this is derived from the Sun code - it is a bit simpler and has int input */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define NSEGS (8) /* Number of A-law segments. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#ifdef __STDC__
uchar Slinear2alaw(int linear) {
#else
uchar Slinear2alaw(linear) int linear; {
#endif
int seg;
uchar aval, mask;
static sshort seg_aend[NSEGS] = {0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff};
linear = linear >> 3;
if(linear >= 0) {
mask = 0xd5; /* sign (7th) bit = 1 */
} else {
mask = 0x55; /* sign bit = 0 */
linear = -linear - 1;
}
/* Convert the scaled magnitude to segment number. */
for(seg = 0; seg < NSEGS && linear > seg_aend[seg]; seg++);
/* Combine the sign, segment, and quantization bits. */
if(seg >= NSEGS) /* out of range, return maximum value. */
return (uchar) (0x7F ^ mask);
else {
aval = (uchar) seg << SEG_SHIFT;
if (seg < 2)
aval |= (linear >> 1) & QUANT_MASK;
else
aval |= (linear >> seg) & QUANT_MASK;
return (aval ^ mask);
}
}

View file

@ -0,0 +1,146 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "shorten.h"
#define MASKTABSIZE 33
ulong masktab[MASKTABSIZE];
void mkmasktab() {
int i;
ulong val = 0;
masktab[0] = val;
for(i = 1; i < MASKTABSIZE; i++) {
val <<= 1;
val |= 1;
masktab[i] = val;
}
}
void var_get_init(shn_file *this_shn)
{
mkmasktab();
this_shn->decode_state->getbuf = (uchar*) pmalloc((ulong) BUFSIZ,this_shn);
this_shn->decode_state->getbufp = this_shn->decode_state->getbuf;
this_shn->decode_state->nbyteget = 0;
this_shn->decode_state->gbuffer = 0;
this_shn->decode_state->nbitget = 0;
}
ulong word_get(shn_file *this_shn)
{
ulong buffer;
int bytes;
if(this_shn->decode_state->nbyteget < 4)
{
this_shn->vars.last_file_position = this_shn->vars.bytes_read;
bytes = fread((uchar*) this_shn->decode_state->getbuf, 1, BUFSIZ, this_shn->vars.fd);
this_shn->decode_state->nbyteget += bytes;
if(this_shn->decode_state->nbyteget < 4) {
shn_error_fatal(this_shn,"Premature EOF on compressed stream -\npossible corrupt or truncated file");
return (ulong)0;
}
this_shn->vars.bytes_read += bytes;
this_shn->decode_state->getbufp = this_shn->decode_state->getbuf;
}
buffer = (((slong) (this_shn->decode_state->getbufp[0])) << 24) | (((slong) (this_shn->decode_state->getbufp[1])) << 16) |
(((slong) (this_shn->decode_state->getbufp[2])) << 8) | ((slong) (this_shn->decode_state->getbufp[3]));
this_shn->decode_state->getbufp += 4;
this_shn->decode_state->nbyteget -= 4;
return(buffer);
}
slong uvar_get(int nbin,shn_file *this_shn)
{
slong result;
if (this_shn->vars.reading_function_code) {
this_shn->vars.last_file_position_no_really = this_shn->vars.last_file_position;
}
if(this_shn->decode_state->nbitget == 0)
{
this_shn->decode_state->gbuffer = word_get(this_shn);
if (this_shn->vars.fatal_error)
return (ulong)0;
this_shn->decode_state->nbitget = 32;
}
for(result = 0; !(this_shn->decode_state->gbuffer & (1L << --(this_shn->decode_state->nbitget))); result++)
{
if(this_shn->decode_state->nbitget == 0)
{
this_shn->decode_state->gbuffer = word_get(this_shn);
if (this_shn->vars.fatal_error)
return (ulong)0;
this_shn->decode_state->nbitget = 32;
}
}
while(nbin != 0)
{
if(this_shn->decode_state->nbitget >= nbin)
{
result = (result << nbin) | ((this_shn->decode_state->gbuffer >> (this_shn->decode_state->nbitget-nbin)) &masktab[nbin]);
this_shn->decode_state->nbitget -= nbin;
nbin = 0;
}
else
{
result = (result << this_shn->decode_state->nbitget) | (this_shn->decode_state->gbuffer & masktab[this_shn->decode_state->nbitget]);
this_shn->decode_state->gbuffer = word_get(this_shn);
if (this_shn->vars.fatal_error)
return (ulong)0;
nbin -= this_shn->decode_state->nbitget;
this_shn->decode_state->nbitget = 32;
}
}
return(result);
}
ulong ulong_get(shn_file *this_shn)
{
unsigned int nbit = uvar_get(ULONGSIZE,this_shn);
if (this_shn->vars.fatal_error)
return (ulong)0;
return(uvar_get(nbit,this_shn));
}
slong var_get(int nbin,shn_file *this_shn)
{
ulong uvar = uvar_get(nbin + 1,this_shn);
if (this_shn->vars.fatal_error)
return (slong)0;
if(uvar & 1) return((slong) ~(uvar >> 1));
else return((slong) (uvar >> 1));
}
void var_get_quit(shn_file *this_shn)
{
free((void *) this_shn->decode_state->getbuf);
this_shn->decode_state->getbuf = NULL;
}

View file

@ -0,0 +1,267 @@
/* wave.c - functions to parse and verify WAVE headers
* Copyright (C) 2000-2004 Jason Jordan <shnutils@freeshell.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* $Id$
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include "shorten.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
//int is_valid_file(shn_file *info)
/* determines whether the given filename (info->filename) is a regular file, and is readable */
/*{
struct stat sz;
FILE *f;
if (0 != stat(info->wave_header.filename,&sz)) {
if (errno == ENOENT)
shn_error("cannot open '%s' because it does not exist",info->wave_header.filename);
else if (errno == EACCES)
shn_error("cannot open '%s' due to insufficient permissions",info->wave_header.filename);
else if (errno == EFAULT)
shn_error("cannot open '%s' due to bad address",info->wave_header.filename);
else if (errno == ENOMEM)
shn_error("cannot open '%s' because the kernel ran out of memory",info->wave_header.filename);
else if (errno == ENAMETOOLONG)
shn_error("cannot open '%s' because the file name is too long",info->wave_header.filename);
else
shn_error("cannot open '%s' due to an unknown problem",info->wave_header.filename);
return 0;
}
if (0 == S_ISREG(sz.st_mode)) {
if (S_ISLNK(sz.st_mode))
shn_error("'%s' is a symbolic link, not a regular file",info->wave_header.filename);
else if (S_ISDIR(sz.st_mode))
shn_error("'%s' is a directory, not a regular file",info->wave_header.filename);
else if (S_ISCHR(sz.st_mode))
shn_error("'%s' is a character device, not a regular file",info->wave_header.filename);
else if (S_ISBLK(sz.st_mode))
shn_error("'%s' is a block device, not a regular file",info->wave_header.filename);
else if (S_ISFIFO(sz.st_mode))
shn_error("'%s' is a fifo, not a regular file",info->wave_header.filename);
else if (S_ISSOCK(sz.st_mode))
shn_error("'%s' is a socket, not a regular file",info->wave_header.filename);
return 0;
}
info->wave_header.actual_size = (ulong)sz.st_size;
if (NULL == (f = fopen(info->wave_header.filename,"rb"))) {
shn_error("could not open '%s': %s",info->wave_header.filename,strerror(errno));
return 0;
}
fclose(f);
return 1;
}*/
int shn_verify_header(shn_file *this_shn)
{
ulong l;
int cur = 0;
/* if (0 == is_valid_file(this_shn))
{
shn_debug(this_shn->config, "while processing '%s': something went wrong while opening this file, see above",this_shn->wave_header.filename);
return 0;
}*/
if (this_shn->vars.bytes_in_header < CANONICAL_HEADER_SIZE) {
shn_debug(this_shn->config, "while processing '%s': header is only %d bytes (should be at least %d bytes)",
this_shn->wave_header.filename,this_shn->vars.bytes_in_header,CANONICAL_HEADER_SIZE);
return 0;
}
if (WAVE_RIFF != shn_uchar_to_ulong_le(this_shn->vars.header+cur))
{
if (AIFF_FORM == shn_uchar_to_ulong_le(this_shn->vars.header+cur))
shn_debug(this_shn->config, "while processing '%s': file contains AIFF data, which is currently not supported",this_shn->wave_header.filename);
else
shn_debug(this_shn->config, "while processing '%s': WAVE header is missing RIFF tag - possible corrupt file",this_shn->wave_header.filename);
return 0;
}
cur += 4;
this_shn->wave_header.chunk_size = shn_uchar_to_ulong_le(this_shn->vars.header+cur);
cur += 4;
if (WAVE_WAVE != shn_uchar_to_ulong_le(this_shn->vars.header+cur))
{
shn_debug(this_shn->config, "while processing '%s': WAVE header is missing WAVE tag",this_shn->wave_header.filename);
return 0;
}
cur += 4;
for (;;)
{
cur += 4;
l = shn_uchar_to_ulong_le(this_shn->vars.header+cur);
cur += 4;
if (WAVE_FMT == shn_uchar_to_ulong_le(this_shn->vars.header+cur-8))
break;
cur += l;
}
if (l < 16)
{
shn_debug(this_shn->config, "while processing '%s': fmt chunk in WAVE header was too short",this_shn->wave_header.filename);
return 0;
}
this_shn->wave_header.wave_format = shn_uchar_to_ushort_le(this_shn->vars.header+cur);
cur += 2;
switch (this_shn->wave_header.wave_format)
{
case WAVE_FORMAT_PCM:
break;
default:
shn_debug(this_shn->config, "while processing '%s': unsupported format 0x%04x (%s) - only PCM data is supported at this time",
this_shn->wave_header.filename,this_shn->wave_header.wave_format,shn_format_to_str(this_shn->wave_header.wave_format));
return 0;
}
this_shn->wave_header.channels = shn_uchar_to_ushort_le(this_shn->vars.header+cur);
cur += 2;
this_shn->wave_header.samples_per_sec = shn_uchar_to_ulong_le(this_shn->vars.header+cur);
cur += 4;
this_shn->wave_header.avg_bytes_per_sec = shn_uchar_to_ulong_le(this_shn->vars.header+cur);
cur += 4;
this_shn->wave_header.block_align = shn_uchar_to_ushort_le(this_shn->vars.header+cur);
cur += 2;
this_shn->wave_header.bits_per_sample = shn_uchar_to_ushort_le(this_shn->vars.header+cur);
cur += 2;
if (this_shn->wave_header.bits_per_sample != 8 && this_shn->wave_header.bits_per_sample != 16)
{
shn_debug(this_shn->config, "while processing '%s': bits per sample is neither 8 nor 16",this_shn->wave_header.filename);
return 0;
}
l -= 16;
if (l > 0)
cur += l;
for (;;)
{
cur += 4;
l = shn_uchar_to_ulong_le(this_shn->vars.header+cur);
cur += 4;
if (WAVE_DATA == shn_uchar_to_ulong_le(this_shn->vars.header+cur-8))
break;
cur += l;
}
this_shn->wave_header.rate = ((uint)this_shn->wave_header.samples_per_sec *
(uint)this_shn->wave_header.channels *
(uint)this_shn->wave_header.bits_per_sample) / 8;
this_shn->wave_header.header_size = cur;
this_shn->wave_header.data_size = l;
this_shn->wave_header.total_size = this_shn->wave_header.chunk_size + 8;
this_shn->wave_header.length = this_shn->wave_header.data_size / this_shn->wave_header.rate;
this_shn->wave_header.exact_length = (double)this_shn->wave_header.data_size / (double)this_shn->wave_header.rate;
if (this_shn->wave_header.channels == CD_CHANNELS &&
this_shn->wave_header.bits_per_sample == CD_BITS_PER_SAMPLE &&
this_shn->wave_header.samples_per_sec == CD_SAMPLES_PER_SEC &&
this_shn->wave_header.avg_bytes_per_sec == CD_RATE &&
this_shn->wave_header.rate == CD_RATE)
{
if (this_shn->wave_header.data_size < CD_MIN_BURNABLE_SIZE)
this_shn->wave_header.problems |= PROBLEM_CD_BUT_TOO_SHORT;
if (this_shn->wave_header.data_size % CD_BLOCK_SIZE != 0)
this_shn->wave_header.problems |= PROBLEM_CD_BUT_BAD_BOUND;
}
else
this_shn->wave_header.problems |= PROBLEM_NOT_CD_QUALITY;
if (this_shn->wave_header.header_size != CANONICAL_HEADER_SIZE)
this_shn->wave_header.problems |= PROBLEM_HEADER_NOT_CANONICAL;
if ((ulong)this_shn->wave_header.header_size + this_shn->wave_header.data_size > this_shn->wave_header.total_size)
this_shn->wave_header.problems |= PROBLEM_HEADER_INCONSISTENT;
if ((ulong)this_shn->wave_header.header_size + this_shn->wave_header.data_size < this_shn->wave_header.total_size)
this_shn->wave_header.problems |= PROBLEM_EXTRA_CHUNKS;
shn_length_to_str(this_shn);
/* header looks ok */
return 1;
}
char *shn_format_to_str(ushort format)
{
switch (format) {
case WAVE_FORMAT_UNKNOWN:
return "Microsoft Official Unknown";
case WAVE_FORMAT_PCM:
return "Microsoft PCM";
case WAVE_FORMAT_ADPCM:
return "Microsoft ADPCM";
case WAVE_FORMAT_IEEE_FLOAT:
return "IEEE Float";
case WAVE_FORMAT_ALAW:
return "Microsoft A-law";
case WAVE_FORMAT_MULAW:
return "Microsoft U-law";
case WAVE_FORMAT_OKI_ADPCM:
return "OKI ADPCM format";
case WAVE_FORMAT_IMA_ADPCM:
return "IMA ADPCM";
case WAVE_FORMAT_DIGISTD:
return "Digistd format";
case WAVE_FORMAT_DIGIFIX:
return "Digifix format";
case WAVE_FORMAT_DOLBY_AC2:
return "Dolby AC2";
case WAVE_FORMAT_GSM610:
return "GSM 6.10";
case WAVE_FORMAT_ROCKWELL_ADPCM:
return "Rockwell ADPCM";
case WAVE_FORMAT_ROCKWELL_DIGITALK:
return "Rockwell DIGITALK";
case WAVE_FORMAT_G721_ADPCM:
return "G.721 ADPCM";
case WAVE_FORMAT_G728_CELP:
return "G.728 CELP";
case WAVE_FORMAT_MPEG:
return "MPEG";
case WAVE_FORMAT_MPEGLAYER3:
return "MPEG Layer 3";
case WAVE_FORMAT_G726_ADPCM:
return "G.726 ADPCM";
case WAVE_FORMAT_G722_ADPCM:
return "G.722 ADPCM";
}
return "Unknown";
}

View file

@ -0,0 +1,5 @@
noinst_PROGRAMS = mkbshift
mkbshift_SOURCES = Sulawalaw.c array.c exit.c mkbshift.c
EXTRA_DIST = mkbshift.h

View file

@ -0,0 +1,192 @@
/*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#include "mkbshift.h"
int Sulaw2lineartab[] = {-32124, -31100, -30076, -29052, -28028, -27004,
-25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812,
-17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436,
-12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828,
-8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884,
-5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644,
-3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364,
-2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500,
-1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876,
-844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524,
-492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276,
-260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112,
-104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0,
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908,
21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460,
13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340,
8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884,
5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516,
3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108,
1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308,
1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684,
652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308,
292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104,
96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0};
#ifndef Sulaw2linear
#ifdef __STDC__
int Sulaw2linear(uchar ulaw) {
#else
int Sulaw2linear(ulaw) uchar ulaw; {
#endif
return(Sulaw2lineartab[ulaw]);
}
#endif
/* adapted by ajr for int input */
#ifdef __STDC__
uchar Slinear2ulaw(int sample) {
#else
uchar Slinear2ulaw(sample) int sample; {
#endif
/*
** This routine converts from linear to ulaw.
**
** Craig Reese: IDA/Supercomputing Research Center
** Joe Campbell: Department of Defense
** 29 September 1989
**
** References:
** 1) CCITT Recommendation G.711 (very difficult to follow)
** 2) "A New Digital Technique for Implementation of Any
** Continuous PCM Companding Law," Villeret, Michel,
** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
** 1973, pg. 11.12-11.17
** 3) MIL-STD-188-113,"Interoperability and Performance Standards
** for Analog-to_Digital Conversion Techniques,"
** 17 February 1987
**
** Input: Signed 16 bit linear sample
** Output: 8 bit ulaw sample
*/
#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
#define CLIP 32635
static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
int sign, exponent, mantissa;
uchar ulawbyte;
/* Get the sample into sign-magnitude. */
if(sample < 0) {
sign = 0x80;
sample = -sample;
}
else
sign = 0;
/* clip the magnitude */
if(sample > CLIP) sample = CLIP;
/* Convert from 16 bit linear to ulaw. */
sample = sample + BIAS;
exponent = exp_lut[( sample >> 7 ) & 0xFF];
mantissa = (sample >> (exponent + 3)) & 0x0F;
ulawbyte = ~(sign | (exponent << 4) | mantissa);
return(ulawbyte);
}
/******************
* ALAW starts here
*/
int Salaw2lineartab[] = {-5504, -5248, -6016, -5760, -4480, -4224,
-4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648,
-4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064,
-23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256,
-31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032,
-11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616,
-13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264,
-312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72,
-120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136,
-184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656,
-752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816,
-784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008,
2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136,
3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496,
12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616,
13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296,
472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56,
40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440,
1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760,
1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976,
816, 784, 880, 848};
#ifndef Salaw2linear
#ifdef __STDC__
int Salaw2linear(uchar alaw) {
#else
int Salaw2linear(alaw) uchar alaw; {
#endif
return(Salaw2lineartab[alaw]);
}
#endif
/* this is derived from the Sun code - it is a bit simpler and has int input */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define NSEGS (8) /* Number of A-law segments. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#ifdef __STDC__
uchar Slinear2alaw(int linear) {
#else
uchar Slinear2alaw(linear) int linear; {
#endif
int seg;
uchar aval, mask;
static sshort seg_aend[NSEGS] = {0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff};
linear = linear >> 3;
if(linear >= 0) {
mask = 0xd5; /* sign (7th) bit = 1 */
} else {
mask = 0x55; /* sign bit = 0 */
linear = -linear - 1;
}
/* Convert the scaled magnitude to segment number. */
for(seg = 0; seg < NSEGS && linear > seg_aend[seg]; seg++);
/* Combine the sign, segment, and quantization bits. */
if(seg >= NSEGS) /* out of range, return maximum value. */
return (uchar) (0x7F ^ mask);
else {
aval = (uchar) seg << SEG_SHIFT;
if (seg < 2)
aval |= (linear >> 1) & QUANT_MASK;
else
aval |= (linear >> seg) & QUANT_MASK;
return (aval ^ mask);
}
}

View file

@ -0,0 +1,63 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include "mkbshift.h"
void *pmalloc(size) ulong size; {
void *ptr;
#if defined(DOS_MALLOC_FEATURE) && !defined(_WINDOWS) /* mrhmod */
fprintf(stderr, "requesting %ld bytes: ", size);
#endif
ptr = malloc(size);
#if defined(DOS_MALLOC_FEATURE) && !defined(_WINDOWS) /* mrhmod */
if(ptr == NULL)
fprintf(stderr, "denied\n");
else
fprintf(stderr, "accepted\n");
#endif
if(ptr == NULL)
perror_exit("call to malloc(%ld) failed in pmalloc()", size);
return(ptr);
}
slong **long2d(n0, n1) ulong n0, n1; {
slong **array0;
if((array0 = (slong**) pmalloc((ulong) (n0 * sizeof(slong*) +
n0 * n1 * sizeof(slong)))) != NULL ) {
slong *array1 = (slong*) (array0 + n0);
int i;
for(i = 0; i < n0; i++)
array0[i] = array1 + i * n1;
}
return(array0);
}
float **float2d(n0, n1) ulong n0, n1; {
float **array0;
if((array0 = (float**) pmalloc((ulong) (n0 * sizeof(float*) +
n0 * n1 * sizeof(float)))) != NULL ) {
float *array1 = (float*) (array0 + n0);
int i;
for(i = 0; i < n0; i++)
array0[i] = array1 + i * n1;
}
return(array0);
}

View file

@ -0,0 +1,230 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef MSDOS
#include <unistd.h>
#include <errno.h>
#endif
#include <setjmp.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "mkbshift.h"
extern char *argv0;
extern char *filenameo;
extern FILE *fileo;
#ifdef _WINDOWS
/* mrhmod - warn about attempt to use stderr (use perror_exit()/error_exit() instead) */
char *stderrWarningMsg = "caught attempt to use stderr";
#endif
jmp_buf exitenv;
char *exitmessage;
/***************************************************************************/
void basic_exit(exitcode) int exitcode; {
/* try to delete the output file on all abnormal exit conditions */
if(exitcode != 0 && fileo != NULL && fileo != stdout)
{
fclose(fileo);
unlink(filenameo);
}
if(exitmessage == NULL)
exit(exitcode < 0 ? 0 : exitcode);
else
longjmp(exitenv, exitcode);
}
/****************************************************************************
** error_exit() - standard error handler with printf() syntax
*/
# ifdef HAVE_STDARG_H
void error_exit(char* fmt, ...) {
va_list args;
va_start(args, fmt);
# else
void error_exit(va_alist) va_dcl {
va_list args;
char *fmt;
va_start(args);
fmt = va_arg(args, char*);
# endif
if(exitmessage == NULL)
{
/*
#if defined(_WINDOWS) && defined(_DEBUG) && !defined(WIN32)
_asm { int 3 } / * mrhmod - catch if debugging * /
#endif
*/
#ifndef _WINDOWS /* mrhmod - must use exitmessage 'cos stderr not available */
fprintf(stderr, "%s: ", argv0);
(void) vfprintf(stderr, fmt, args);
#endif /* _WINDOWS */
}
else
{
(void) vsprintf(exitmessage, fmt, args);
strcat(exitmessage, "\n");
}
va_end(args);
basic_exit(errno);
}
/****************************************************************************
** perror_exit() - system error handler with printf() syntax
**
** Appends system error message based on errno
*/
# ifdef HAVE_STDARG_H
void perror_exit(char* fmt, ...) {
va_list args;
va_start(args, fmt);
# else
void perror_exit(va_alist) va_dcl {
va_list args;
char *fmt;
va_start(args);
fmt = va_arg(args, char*);
# endif
if(exitmessage == NULL) {
/*
#if defined(_WINDOWS) && defined(_DEBUG) && !defined(WIN32)
_asm { int 3 } / * mrhmod - catch if debugging * /
#endif
*/
#ifndef _WINDOWS /* mrhmod - must use exitmessage 'cos stderr not available */
fprintf(stderr, "%s: ", argv0);
(void) vfprintf(stderr, fmt, args);
(void) fprintf(stderr, ": ");
#ifndef MSDOS
perror("\0");
#endif
#endif /* _WINDOWS */
}
else {
(void) vsprintf(exitmessage, fmt, args);
strcat(exitmessage, ": ");
strcat(exitmessage,strerror(errno));
strcat(exitmessage, "\n");
}
va_end(args);
basic_exit(errno);
}
# ifdef HAVE_STDARG_H
void usage_exit(int exitcode, char* fmt, ...) {
va_list args;
va_start(args, fmt);
# else
void usage_exit(va_alist) va_dcl {
va_list args;
int exitcode;
char *fmt;
va_start(args);
exitcode = va_arg(args, int);
fmt = va_arg(args, char*);
# endif
if(exitmessage == NULL) {
#if defined(_WINDOWS) && defined(_DEBUG) && !defined(WIN32)
_asm { int 3 } /* mrhmod - catch if debugging */
#endif
#ifndef _WINDOWS /* mrhmod - must use exitmessage 'cos stderr not available */
if(fmt != NULL) {
fprintf(stderr, "%s: ", argv0);
(void) vfprintf(stderr, fmt, args);
}
fprintf(stderr, "%s: for more information use: %s -h\n", argv0, argv0);
#endif /* _WINDOWS */
}
else
{
(void) vsprintf(exitmessage, fmt, args);
strcat(exitmessage, "\n");
}
va_end(args);
basic_exit(exitcode);
}
# ifdef HAVE_STDARG_H
void update_exit(int exitcode, char* fmt, ...) {
va_list args;
va_start(args, fmt);
# else
void update_exit(va_alist) va_dcl {
va_list args;
int exitcode;
char *fmt;
va_start(args);
exitcode = va_arg(args, int);
fmt = va_arg(args, char*);
# endif
if(exitmessage == NULL) {
#if defined(_WINDOWS) && defined(_DEBUG) && !defined(WIN32)
_asm { int 3 } /* mrhmod - catch if debugging */
#endif
#ifndef _WINDOWS /* mrhmod - must use exitmessage 'cos stderr not available */
if(fmt != NULL) {
fprintf(stderr, "%s: ", argv0);
(void) vfprintf(stderr, fmt, args);
}
fprintf(stderr, "%s: version %s\n",argv0,VERSION);
fprintf(stderr, "%s: please report this problem to ajr@softsound.com\n", argv0);
#endif /* _WINDOWS */
}
#ifdef _WINDOWS /* mrhmod - output something */
error_exit( fmt, args );
#endif
va_end(args);
basic_exit(exitcode);
}

View file

@ -0,0 +1,110 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#include <stdio.h>
#include "mkbshift.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define USIZE 256
#define HUSIZE 128
#define SHIFTSIZE 13
char *argv0 = "mkbshift";
char *filenameo = NULL;
FILE *fileo = NULL;
int main() {
FILE *fout;
char *filename = "bitshift.h", *writemode = "w";
int shift, i;
int tab[USIZE];
slong sample;
slong **forwardmap = long2d((ulong) SHIFTSIZE, (ulong) USIZE);
slong **reversemap = long2d((ulong) SHIFTSIZE, (ulong) USIZE);
fout = fopen(filename, writemode);
if(fout == NULL)
perror_exit("fopen(\"%s\", \"%s\")", filename, writemode);
for(i = 0; i < USIZE; i++) tab[i] = 0;
/* brute force search of the largest number of zero bits in a linear value */
for(shift = 0; shift < SHIFTSIZE; shift++)
for(sample = -(1L << 15); sample < (1L << 15); sample += 1 << (shift + 3))
tab[Slinear2ulaw(sample)] = shift;
/* print this out as a lookup table */
fprintf(fout, "char ulaw_maxshift[%d] = {", USIZE);
for(i = 0; i < USIZE - 1; i++)
fprintf(fout, "%d,", tab[i]);
fprintf(fout, "%d};\n\n", tab[USIZE - 1]);
/* compute the greatest inward shift compatable with ??? */
for(shift = 0; shift < SHIFTSIZE; shift++) {
int nused;
nused = 0;
for(i = 255; i >= 128; i--)
if(tab[i] >= shift) forwardmap[shift][i] = nused++;
for(i = 255; i >= 128; i--)
if(tab[i] < shift) forwardmap[shift][i] = nused++;
nused = -1;
for(i = 126; i >= 0; i--)
if(tab[i] >= shift) forwardmap[shift][i] = nused--;
forwardmap[shift][127] = nused--;
for(i = 126; i >= 0; i--)
if(tab[i] < shift) forwardmap[shift][i] = nused--;
for(i = 0; i < USIZE; i++)
reversemap[shift][forwardmap[shift][i] + HUSIZE] = i;
}
/* simple check */
for(shift = 0; shift < SHIFTSIZE; shift++)
for(i = 0; i < USIZE; i++)
if(forwardmap[shift][reversemap[shift][i]] != i - HUSIZE)
error_exit("identity maping failed for shift: %d\tindex: %d\n",shift,i);
/* print out the ulaw_inward lookup table */
fprintf(fout, "schar ulaw_inward[%d][%d] = {\n", SHIFTSIZE, USIZE);
for(shift = 0; shift < SHIFTSIZE; shift++) {
fprintf(fout, "{");
for(i = 0; i < USIZE - 1; i++)
fprintf(fout, "%ld,", forwardmap[shift][i]);
if(shift != SHIFTSIZE - 1)
fprintf(fout, "%ld},\n", forwardmap[shift][USIZE - 1]);
else
fprintf(fout, "%ld}\n};\n", forwardmap[shift][USIZE - 1]);
}
fprintf(fout, "\n");
/* print out the ulaw_outward lookup table */
fprintf(fout, "uchar ulaw_outward[%d][%d] = {\n", SHIFTSIZE, USIZE);
for(shift = 0; shift < SHIFTSIZE; shift++) {
fprintf(fout, "{");
for(i = 0; i < USIZE - 1; i++)
fprintf(fout, "%ld,", reversemap[shift][i]);
if(shift != SHIFTSIZE - 1)
fprintf(fout, "%ld},\n", reversemap[shift][USIZE - 1]);
else
fprintf(fout, "%ld}\n};\n", reversemap[shift][USIZE - 1]);
}
fclose(fout);
/* exit happy */
return(0);
}

View file

@ -0,0 +1,237 @@
/******************************************************************************
* *
* Copyright (C) 1992-1995 Tony Robinson *
* *
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
* *
******************************************************************************/
/*
* $Id$
*/
#ifndef _MKBSHIFT_H
#define _MKBSHIFT_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef HAVE_STRERROR
extern char *sys_errlist[];
#define strerror(x) sys_errlist[x]
#endif
#define MAGIC "ajkg"
#define FORMAT_VERSION 2
#define MIN_SUPPORTED_VERSION 1
#define MAX_SUPPORTED_VERSION 3
#define MAX_VERSION 7
#define UNDEFINED_UINT -1
#define DEFAULT_BLOCK_SIZE 256
#define DEFAULT_V0NMEAN 0
#define DEFAULT_V2NMEAN 4
#define DEFAULT_MAXNLPC 0
#define DEFAULT_NCHAN 1
#define DEFAULT_NSKIP 0
#define DEFAULT_NDISCARD 0
#define NBITPERLONG 32
#define DEFAULT_MINSNR 256
#define DEFAULT_MAXRESNSTR "32.0"
#define DEFAULT_QUANTERROR 0
#define MINBITRATE 2.5
#define MAX_LPC_ORDER 64
#define CHANSIZE 0
#define ENERGYSIZE 3
#define BITSHIFTSIZE 2
#define NWRAP 3
#define FNSIZE 2
#define FN_DIFF0 0
#define FN_DIFF1 1
#define FN_DIFF2 2
#define FN_DIFF3 3
#define FN_QUIT 4
#define FN_BLOCKSIZE 5
#define FN_BITSHIFT 6
#define FN_QLPC 7
#define FN_ZERO 8
#define FN_VERBATIM 9
#define VERBATIM_CKSIZE_SIZE 5 /* a var_put code size */
#define VERBATIM_BYTE_SIZE 8 /* code size 8 on single bytes means
* no compression at all */
#define VERBATIM_CHUNK_MAX 256 /* max. size of a FN_VERBATIM chunk */
#define ULONGSIZE 2
#define NSKIPSIZE 1
#define LPCQSIZE 2
#define LPCQUANT 5
#define XBYTESIZE 7
#define TYPESIZE 4
#define TYPE_AU1 0 /* original lossless ulaw */
#define TYPE_S8 1 /* signed 8 bit characters */
#define TYPE_U8 2 /* unsigned 8 bit characters */
#define TYPE_S16HL 3 /* signed 16 bit shorts: high-low */
#define TYPE_U16HL 4 /* unsigned 16 bit shorts: high-low */
#define TYPE_S16LH 5 /* signed 16 bit shorts: low-high */
#define TYPE_U16LH 6 /* unsigned 16 bit shorts: low-high */
#define TYPE_ULAW 7 /* lossy ulaw: internal conversion to linear */
#define TYPE_AU2 8 /* new ulaw with zero mapping */
#define TYPE_AU3 9 /* lossless alaw */
#define TYPE_ALAW 10 /* lossy alaw: internal conversion to linear */
#define TYPE_RIFF_WAVE 11 /* Microsoft .WAV files */
#define TYPE_EOF 12
#define TYPE_GENERIC_ULAW 128
#define TYPE_GENERIC_ALAW 129
#define POSITIVE_ULAW_ZERO 0xff
#define NEGATIVE_ULAW_ZERO 0x7f
#undef BOOL
#undef TRUE
#undef FALSE
#define BOOL int
#define TRUE 1
#define FALSE 0
#ifndef MAX_PATH
#define MAX_PATH 2048
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#if defined(unix) && !defined(linux)
#define labs abs
#endif
#define ROUNDEDSHIFTDOWN(x, n) (((n) == 0) ? (x) : ((x) >> ((n) - 1)) >> 1)
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* BUFSIZ must be a multiple of four to contain a whole number of words */
#ifdef BUFSIZ
#undef BUFSIZ
#endif
#define BUFSIZ 512
#define putc_exit(val, stream)\
{ char rval;\
if((rval = putc((val), (stream))) != (char) (val))\
update_exit(1, "write failed: putc returns EOF\n");\
}
extern int getc_exit_val;
#define getc_exit(stream)\
(((getc_exit_val = getc(stream)) == EOF) ? \
update_exit(1, "read failed: getc returns EOF\n"), 0: getc_exit_val)
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#else
# if SIZEOF_UNSIGNED_LONG == 4
# define uint32_t unsigned long
# define int32_t long
# else
# define uint32_t unsigned int
# define int32_t int
# endif
# define uint16_t unsigned short
# define uint8_t unsigned char
# define int16_t short
# define int8_t char
#endif
#undef ulong
#undef ushort
#undef uchar
#undef slong
#undef sshort
#undef schar
#define ulong uint32_t
#define ushort uint16_t
#define uchar uint8_t
#define slong int32_t
#define sshort int16_t
#define schar int8_t
#if defined(__STDC__) || defined(__GNUC__) || defined(sgi) || !defined(unix)
#define PROTO(ARGS) ARGS
#else
#define PROTO(ARGS) ()
#endif
#ifdef NEED_OLD_PROTOTYPES
/*******************************************/
/* this should be in string.h or strings.h */
extern int strcmp PROTO ((const char*, const char*));
extern char* strcpy PROTO ((char*, const char*));
extern char* strcat PROTO ((char*, const char*));
extern int strlen PROTO ((const char*));
/**************************************/
/* defined in stdlib.h if you have it */
extern void* malloc PROTO ((unsigned long));
extern void free PROTO ((void*));
extern int atoi PROTO ((const char*));
extern void swab PROTO ((char*, char*, int));
extern int fseek PROTO ((FILE*, long, int));
/***************************/
/* other misc system calls */
extern int unlink PROTO ((const char*));
extern void exit PROTO ((int));
#endif
/**************************/
/* defined in Sulawalaw.c */
extern int Sulaw2lineartab[];
#define Sulaw2linear(i) (Sulaw2lineartab[i])
#ifndef Sulaw2linear
extern int Sulaw2linear PROTO((uchar));
#endif
extern uchar Slinear2ulaw PROTO((int));
extern int Salaw2lineartab[];
#define Salaw2linear(i) (Salaw2lineartab[i])
#ifndef Salaw2linear
extern int Salaw2linear PROTO((uchar));
#endif
extern uchar Slinear2alaw PROTO((int));
/*********************/
/* defined in exit.c */
extern void basic_exit PROTO ((int));
#ifdef HAVE_STDARG_H
extern void error_exit PROTO ((char*,...));
extern void perror_exit PROTO ((char*,...));
extern void usage_exit PROTO ((int, char*,...));
extern void update_exit PROTO ((int, char*,...));
#else
extern void error_exit PROTO (());
extern void perror_exit PROTO (());
extern void usage_exit PROTO (());
extern void update_exit PROTO (());
#endif
/**********************/
/* defined in array.c */
extern void* pmalloc PROTO ((ulong));
extern slong** long2d PROTO ((ulong, ulong));
#endif

View file

@ -0,0 +1,7 @@
libdir = `lamip --plugin-dir`
lib_LTLIBRARIES = libinputshorten.la
INCLUDES = -I. -I.. -I$(top_srcdir)/shorten -I$(top_srcdir)/shorten/util -I$(top_srcdir)/shorten/src
libinputshorten_la_LDFLAGS = -module -avoid-version
libinputshorten_la_LIBADD = $(top_srcdir)/shorten/src/libshorten.la
libinputshorten_la_SOURCES = libinputshorten.c

View file

@ -0,0 +1,250 @@
/*
* lamip input plugin - Shorten decoder
*
*
* well... first version is full of memory leaks i guess :)
*/
/* General includes */
#include <plug_in.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
/* General includes for shorten */
#include "decode.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* we declare the functions we use in the plugin here */
static int shorten_init(const lamipPluginHandle *);
static void shorten_cleanup(void);
static void shorten_decode(lamipURL *, int);
static void shorten_songinfo(lamipURL *,lamipSonginfo *);
/* We set the functions in the InputPlugin struct... */
static InputPlugin shorten_functions;
InputPlugin *lamip_input_info(void)
{
shorten_functions.common.name = "inputSHORTEN";
shorten_functions.common.description = "plays *.shn - Shorten";
shorten_functions.common.init = shorten_init;
shorten_functions.common.cleanup = shorten_cleanup;
shorten_functions.decode = shorten_decode;
shorten_functions.set_song_info = shorten_songinfo;
return(&shorten_functions);
}
/* we set the module PCM format in this struct... like every input plugin should do by now */
static lamipPCMInfo pcmi;
/* some functions */
/* all things for shorten decoder */
shn_file *shnfile;
shn_config shn_cfg;
static uchar *real_buffer = (uchar *)NULL;
#define CONFIG_ERROR_OUTPUT_METHOD "error_output_method"
#define CONFIG_SEEK_TABLES_PATH "seek_tables_path"
#define CONFIG_RELATIVE_SEEK_TABLES_PATH "relative_seek_tables_path"
#define CONFIG_VERBOSE "verbose"
#define CONFIG_SWAP_BYTES "swap_bytes"
#define NUM_BUFFER_BLOCKS 4096L
static int shorten_init(const lamipPluginHandle *handle)
{
/* Setting when shorten decoder should get active */
lamipPluginHandle *config = (lamipPluginHandle *)handle;
lamip_set_mime_type(config, ".shn", NULL);
/* Initializing the shn_cfg struct, we config it later anyway */
shn_cfg.error_output_method = ERROR_OUTPUT_DEVNULL;
shn_cfg.seek_tables_path = NULL;
shn_cfg.relative_seek_tables_path = NULL;
shn_cfg.verbose = 0;
shn_cfg.swap_bytes = 0;
/* Necessary config variables */
char *val_error_output_method;
char *val_seek_tables_path;
char *val_relative_seek_tables_path;
int val_verbose;
int val_swap_bytes;
/* config: error output */
if(!lamip_cfg_getExist(handle, CONFIG_ERROR_OUTPUT_METHOD)) {
lamip_send_message("SHORTEN: shorten_init: no config value for %s found, resetting to default DEVNULL...\n", CONFIG_ERROR_OUTPUT_METHOD);
lamip_send_message("SHORTEN: shorten_init: possible values for %s are \"DEVNULL\", \"STDERR\"\n", CONFIG_ERROR_OUTPUT_METHOD);
val_error_output_method = strdup("DEVNULL");
lamip_cfg_set(config, CONFIG_ERROR_OUTPUT_METHOD, val_error_output_method);
} else {
val_error_output_method = lamip_cfg_get(handle, CONFIG_ERROR_OUTPUT_METHOD);
}
if(strcasecmp(val_error_output_method, "DEVNULL") == 0)
shn_cfg.error_output_method = ERROR_OUTPUT_DEVNULL;
else if(strcasecmp(val_error_output_method, "STDERR") == 0)
shn_cfg.error_output_method = ERROR_OUTPUT_STDERR;
else {
lamip_send_message("SHORTEN: shorten_init: Wrong value for %s found! Resetting to default DEVNULL...\n");
lamip_send_message("SHORTEN: shorten_init: possible values for %s are \"DEVNULL\", \"STDERR\", \"WINDOW\"\n", CONFIG_ERROR_OUTPUT_METHOD);
val_error_output_method = strdup("DEVNULL");
lamip_cfg_set(config, CONFIG_ERROR_OUTPUT_METHOD, val_error_output_method);
shn_cfg.error_output_method = ERROR_OUTPUT_DEVNULL;
}
/* config: absolute seek tables path */
if(!lamip_cfg_getExist(handle, CONFIG_SEEK_TABLES_PATH)) {
lamip_send_message("SHORTEN: shorten_init: no config value for %s found, resetting to default...\n", CONFIG_SEEK_TABLES_PATH);
val_seek_tables_path = strdup("/tmp");
lamip_cfg_set(config, CONFIG_SEEK_TABLES_PATH, val_seek_tables_path);
} else {
val_seek_tables_path = lamip_cfg_get(handle, CONFIG_SEEK_TABLES_PATH);
}
shn_cfg.seek_tables_path = strdup(val_seek_tables_path);
/* config: relative seek tables path */
if(!lamip_cfg_getExist(handle, CONFIG_RELATIVE_SEEK_TABLES_PATH)) {
lamip_send_message("SHORTEN: shorten_init: no config value for %s found, resetting to default...\n", CONFIG_RELATIVE_SEEK_TABLES_PATH);
val_relative_seek_tables_path = strdup("");
lamip_cfg_set(config, CONFIG_RELATIVE_SEEK_TABLES_PATH, val_relative_seek_tables_path);
} else {
val_relative_seek_tables_path = lamip_cfg_get(handle, CONFIG_RELATIVE_SEEK_TABLES_PATH);
}
shn_cfg.relative_seek_tables_path = strdup(val_relative_seek_tables_path);
/* config: verbose */
if(!lamip_cfg_getExist(handle, CONFIG_VERBOSE)) {
lamip_send_message("SHORTEN: shorten_init: no config value for %s found, resetting to default...\n", CONFIG_VERBOSE);
val_verbose = 0;
lamip_cfg_setBool(config, CONFIG_VERBOSE, val_verbose);
} else {
val_verbose = lamip_cfg_getBool(handle, CONFIG_VERBOSE);
}
shn_cfg.verbose = val_verbose;
/* config: swap bytes */
if(!lamip_cfg_getExist(handle, CONFIG_SWAP_BYTES)) {
lamip_send_message("SHORTEN: shorten_init: no config value for %s found, resetting to default...\n", CONFIG_SWAP_BYTES);
val_swap_bytes = 0;
lamip_cfg_setBool(config, CONFIG_SWAP_BYTES, val_swap_bytes);
} else {
val_swap_bytes = lamip_cfg_getBool(handle, CONFIG_SWAP_BYTES);
}
shn_cfg.swap_bytes = val_swap_bytes;
/* Config cleanup */
free(val_error_output_method);
free(val_seek_tables_path);
free(val_relative_seek_tables_path);
return 1;
}
static void shorten_cleanup(void)
{
return;
}
static void shorten_decode(lamipURL *url, int subtrack)
{
if(!url) {
lamip_send_message("SHORTEN: shorten_decode: Got no url!\n");
return;
}
char *filename = lamip_url_getURL(url);
if(!filename) {
lamip_send_message("SHORTEN: shorten_decode: Got no filename! We cannot play from stream by now!\n");
return;
}
shnfile = shn_load(filename, shn_cfg);
if(!shnfile) {
lamip_send_message("SHORTEN: shorten_decode: Error in opening file! Give it another try with skipping id3v2...\n");
return;
}
if(!shn_init_decoder(shnfile)) {
lamip_send_message("SHORTEN: shorten_decode: shn_init_decoder() failed! Aborting...\n");
shn_unload(shnfile);
shnfile = (shn_file *)NULL;
return;
}
pcmi.channels = shn_get_channels(shnfile);
pcmi.samplerate = shn_get_samplerate(shnfile);
switch(shn_get_bitspersample(shnfile)) {
case 8:
pcmi.format = PCM_FORMAT_U8;
break;
case 16:
pcmi.format = PCM_FORMAT_S16_LE;
break;
/* Next two bit depths aren't supported by shorten anyway */
case 24:
pcmi.format = PCM_FORMAT_S24_LE;
break;
case 32:
pcmi.format = PCM_FORMAT_S32_LE;
break;
default:
lamip_send_message("SHORTEN: shorten_decode: Not supported bits_per_sample format!");
}
/* Getting a clean buffer */
int buffer_size = shn_get_buffer_block_size(shnfile, NUM_BUFFER_BLOCKS);
if(real_buffer) {
free(real_buffer);
real_buffer = (uchar *)NULL;
}
if(!real_buffer) {
real_buffer = (uchar *)malloc(20000);
if(!real_buffer) {
lamip_send_message("SHORTEN: shorten_decode: malloc for real_buffer failed! Aborting...\n");
shn_unload(shnfile);
shnfile = (shn_file *)NULL;
return;
}
}
int read_buffer;
int seekable = shn_seekable(shnfile);
lamip_open(&pcmi, shn_get_song_length(shnfile));
while(lamip_isContinue()) {
read_buffer = shn_read(shnfile, real_buffer, buffer_size);
if(read_buffer <= 0) {
lamip_drain();
break;
}
lamip_writeData((uchar *)real_buffer, buffer_size);
/* If seeking */
if(lamip_isSeek() && seekable)
if(!(shn_seek(shnfile, (unsigned int)(lamip_isSeekGetAndReset() / 1000))))
lamip_send_message("SHORTEN: shorten_decode: Seeking failed!\n");
}
lamip_close();
if(!shn_cleanup_decoder(shnfile))
lamip_send_message("SHORTEN: shorten_decode: shn_cleanup_decoder() failed!\n");
shn_unload(shnfile);
shnfile = NULL;
if(real_buffer) {
free((uchar *)real_buffer);
real_buffer = (uchar *)NULL;
}
return;
}
static void shorten_songinfo(lamipURL* url, lamipSonginfo* songinfo)
{
/* TODO - perhaps it ain't necessary... due to a changing lamip core :) */
return;
}

View file

View file

@ -0,0 +1,106 @@
---------------------------
Release 4.2 - April 2, 2005
---------------------------
wavpack.exe (command-line encoder) - 4.2
----------------------------------------
fixed: handling of wav files larger than 2 gig
improved: stereo lossless encoding speed (including "extra" mode)
added: -i option to ignore length specified in wav header
added: -w option to write APEv2 tags directly from command line
wvunpack.exe (command-line decoder) - 4.2
-----------------------------------------
improved: decoding speed
in_wv.dll (winamp plugin) - 2.2
-------------------------------
added: winamp media library support
improved: decoding speed
foo_wavpack.dll (foobar plugin) - 2.2
-------------------------------------
improved: decoding speed
nxWavPack.dll (Nero plugin) - 1.1
Cool_wv4.flt (CoolEdit / Audition filter) - 2.4
-----------------------------------------------
fixed: handling of wav files larger than 2 gig
improved: encoding and decoding speed
WavPack Library Source Code - 4.2
---------------------------------
improved: encoding and decoding speed
fixed: works correctly with 64-bit compilers
added: mode bit to open files in "streaming" mode
--------------------------
Update - December 12, 2004
--------------------------
WavPack_Apollo.dll (Apollo plugin) - 1.2
----------------------------------------
fixed: crash when Apollo opened and WavPack plugin can't find config file
--------------------------------
Release 4.1 - September 14, 2004
--------------------------------
wavpack.exe (command-line encoder) - 4.1
----------------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: mono or multichannel files causing crash (no corruption possible)
added: third name specification for "correction" file (EAC specific)
added: -t option to preserve timestamps
added: error summary for batch mode
wvunpack.exe (command-line decoder) - 4.1
-----------------------------------------
fixed: hybrid mode decoding bugs (very obscure situations)
added: -s option to dump file summary to stdout
added: -t option to preserve timestamps
added: error summary for batch mode
wvselfx.exe (self-extraction stub) - 4.1
----------------------------------------
fixed: hybrid mode decoding bugs (very obscure situations)
in_wv.dll (winamp plugin) - 2.1
-------------------------------
fixed: international characters in tags display properly (UTF-8 to Ansi)
added: maximum tag data field width changed from 64 chars to 128 chars
added: new infobox items including encoder version & modes, track #, md5
foo_wavpack.dll (foobar plugin) - 2.1
-------------------------------------
added: new database items including encoder version & modes and md5
WavPack_Apollo.dll (Apollo plugin) - 1.1
----------------------------------------
fixed: international characters in tags display properly (UTF-8 to Ansi)
Cool_wv4.flt (CoolEdit / Audition filter) - 2.2
-----------------------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: saving mono file causing crash (no corruption possible)
fixed: hybrid mode decoding bugs (very obscure situations)
fixed: partial saves (with "Cancel") have incorrect RIFF header if unpacked
nxWavPack.dll (Nero plugin) - 1.0
---------------------------------
new
WavPack Library Source Code - 4.1
---------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: mono or multichannel files causing crash (no corruption possible)
fixed: hybrid mode decoding bugs (very obscure situations)
added: mode bits for determining additional encode info (extra, sfx)
added: function to return total compressed file length (including wvc)
added: function to return encoder version (1, 2, 3, or 4)
added: ability to obtain MD5 sum before decoding file (requires seek to end)
added: mode bit for determining tag type (for proper character translation)
added: ability to encode WavPack files without knowing length in advance
added: option for small "information only" version of library

View file

@ -0,0 +1,27 @@
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = wavpack wvunpack
lib_LTLIBRARIES = libwavpack.la
wpincludedir = $(prefix)/include/wavpack
wpinclude_HEADERS = md5.h wavpack.h wputils.h unpack3.h
libwavpack_la_SOURCES = bits.c float.c metadata.c unpack.c unpack3.c utils.c \
wputils.c words.c md5.c extra1.c extra2.c pack.c \
md5.h wavpack.h wputils.h unpack3.h
libwavpack_la_CFLAGS = -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3
libwavpack_la_LDFLAGS = -lm @ICONV_LIBS@
wavpack_SOURCES = wavpack.c
wavpack_CFLAGS = -DPACK
wavpack_LDFLAGS = -lm -lcurses
wavpack_LDADD = libwavpack.la
wvunpack_SOURCES = wvunpack.c
wvunpack_CFLAGS = -DUNPACK -DUSE_FSTREAMS
wvunpack_LDFLAGS = -lm -lcurses
wvunpack_LDADD = libwavpack.la
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = wavpack.pc

View file

View file

@ -0,0 +1,86 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
This package contains all the source code required to build the WavPack
command-line programs and the WavPack library and it has been tested on many
platforms. For example code using the library you might want to check some
of the plugin sources in the Windows source release.
To build everything, type:
1. ./autogen.sh
2. ./configure
3. make
4. make install (optionally, to install into /usr/local/bin)
Notes:
1. This code is designed to be much easier to port to other platforms than
the previous version of WavPack. File I/O is done with streams and all file
functions (except "fopen") are handled in a wrapper in the "utils.c"
module. The code is even written to be endian-independent and a compile
option is provided to eliminate the DOS-specific directory searches.
To maintain compatibility on various platforms, the following conventions
are used:
a "short" must be 16-bits
an "int" must be at least 16-bits, but may be larger
a "char" must default to signed (Watcom users take note!)
For version 4.2 references to "long" variables were eliminated to allow
compilation on 64-bit machines.
2. For WavPack file decoding, a library interface in "wputils.c" provides all
the functionality required for both the winamp plugin and the "wvunpack"
command-line program (including the transparent decoding of "correction"
files). There is also an alternate entry point that uses reader callbacks
for all input, although in this case it is the caller's responsibility to
to open the "correction" file. It is no longer necessary to manipulate the
WavPack structures directly; everything is handled with function calls. In
fact, a new header file called "wputils.h" can be used that hides all the
WavPack internals from the application.
3. For WavPack file creation, the library interface in "wputils.c" provides
all the functionality for both the Audition filter and the "wavpack"
command-line program. No file I/O is performed by the library when creating
WavPack files. Instead, the user supplies a "write_block" function that
accepts completed WavPack blocks. For version 4.2 limited functionality
has been added to append APEv2 tags to WavPack files during creation.
4. The following #define's are used to control the optimum configuration of
the library for the desired application and must be the same for the
compilation of ALL files:
UNPACK to unpack audio samples from WavPack files
PACK to create WavPack files from raw audio data
INFO_ONLY to obtain information from WavPack files, but not audio
SEEKING to allow seeking to a specific sample index (unpack only)
USE_FSTREAMS to open WavPack files by name using fstreams (via fopen)
TAGS to read specified fields from ID3v1 and APEv2 tags and
create APEv2 tags
VER3 to handle WavPack files from versions prior to 4.0
WIN32 required for Win32 platform
The following files are required for various configurations:
UNPACK or
INFO_ONLY: wputils.c unpack.c words.c bits.c metadata.c float.c
PACK: wputils.c pack.c extra1.c extra2.c
words.c bits.c metadata.c float.c
PACK and
UNPACK: wputils.c unpack.c pack.c extra1.c extra2.c
words.c bits.c metadata.c float.c
5. An alternate version of this library is available specifically designed
for "resource limited" CPUs or hardware decoding. This "tiny" decoder
library works with less than 32k of code and less than 4k of data.
6. Questions or comments should be directed to david@wavpack.com

View file

@ -0,0 +1,7 @@
#!/bin/sh
touch NEWS README AUTHORS ChangeLog
aclocal
libtoolize --copy
automake --add-missing
autoconf

View file

@ -0,0 +1,259 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// bits.c
// This module provides utilities to support the BitStream structure which is
// used to read and write all WavPack audio data streams. It also contains a
// wrapper for the stream I/O functions and a set of functions dealing with
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
// the malloc() system is provided.
#include "wavpack.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#if defined(WIN32)
#include <io.h>
#else
#include <unistd.h>
#endif
////////////////////////// Bitstream functions ////////////////////////////////
#if defined(UNPACK) || defined(INFO_ONLY)
// Open the specified BitStream and associate with the specified buffer.
static void bs_read (Bitstream *bs);
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end)
{
bs->error = bs->sr = bs->bc = 0;
bs->ptr = (bs->buf = buffer_start) - 1;
bs->end = buffer_end;
bs->wrap = bs_read;
}
// This function is only called from the getbit() and getbits() macros when
// the BitStream has been exhausted and more data is required. Sinve these
// bistreams no longer access files, this function simple sets an error and
// resets the buffer.
static void bs_read (Bitstream *bs)
{
bs->ptr = bs->buf - 1;
bs->error = 1;
}
// This function is called to close the bitstream. It returns the number of
// full bytes actually read as bits.
uint32_t bs_close_read (Bitstream *bs)
{
uint32_t bytes_read;
if (bs->bc < 8)
bs->ptr++;
if ((bs->buf - bs->ptr) & 1)
bs->ptr++;
bytes_read = bs->ptr - bs->buf;
CLEAR (*bs);
return bytes_read;
}
#endif
#ifdef PACK
// Open the specified BitStream using the specified buffer pointers. It is
// assumed that enough buffer space has been allocated for all data that will
// be written, otherwise an error will be generated.
static void bs_write (Bitstream *bs);
void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end)
{
bs->error = bs->sr = bs->bc = 0;
bs->ptr = bs->buf = buffer_start;
bs->end = buffer_end;
bs->wrap = bs_write;
}
// This function is only called from the putbit() and putbits() macros when
// the buffer is full, which is now flagged as an error.
static void bs_write (Bitstream *bs)
{
bs->ptr = bs->buf;
bs->error = 1;
}
// This function forces a flushing write of the specified BitStream, and
// returns the total number of bytes written into the buffer.
uint32_t bs_close_write (Bitstream *bs)
{
uint32_t bytes_written;
if (bs->error)
return (uint32_t) -1;
while (bs->bc || ((bs->ptr - bs->buf) & 1)) putbit_1 (bs);
bytes_written = bs->ptr - bs->buf;
CLEAR (*bs);
return bytes_written;
}
#endif
/////////////////////// Endian Correction Routines ////////////////////////////
void little_endian_to_native (void *data, char *format)
{
uchar *cp = (uchar *) data;
int32_t temp;
while (*format) {
switch (*format) {
case 'L':
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
* (int32_t *) cp = temp;
cp += 4;
break;
case 'S':
temp = cp [0] + (cp [1] << 8);
* (short *) cp = (short) temp;
cp += 2;
break;
default:
if (isdigit (*format))
cp += *format - '0';
break;
}
format++;
}
}
void native_to_little_endian (void *data, char *format)
{
uchar *cp = (uchar *) data;
int32_t temp;
while (*format) {
switch (*format) {
case 'L':
temp = * (int32_t *) cp;
*cp++ = (uchar) temp;
*cp++ = (uchar) (temp >> 8);
*cp++ = (uchar) (temp >> 16);
*cp++ = (uchar) (temp >> 24);
break;
case 'S':
temp = * (short *) cp;
*cp++ = (uchar) temp;
*cp++ = (uchar) (temp >> 8);
break;
default:
if (isdigit (*format))
cp += *format - '0';
break;
}
format++;
}
}
////////////////////////// Debug Wrapper for Malloc ///////////////////////////
#ifdef DEBUG_ALLOC
void *vptrs [512];
static void *add_ptr (void *ptr)
{
int i;
for (i = 0; i < 512; ++i)
if (!vptrs [i]) {
vptrs [i] = ptr;
break;
}
if (i == 512)
error_line ("too many mallocs!");
return ptr;
}
static void *del_ptr (void *ptr)
{
int i;
for (i = 0; i < 512; ++i)
if (vptrs [i] == ptr) {
vptrs [i] = NULL;
break;
}
if (i == 512)
error_line ("free invalid ptr!");
return ptr;
}
void *malloc_db (uint32_t size)
{
if (size)
return add_ptr (malloc (size));
else
return NULL;
}
void free_db (void *ptr)
{
if (ptr)
free (del_ptr (ptr));
}
void *realloc_db (void *ptr, uint32_t size)
{
if (ptr && size)
return add_ptr (realloc (del_ptr (ptr), size));
else if (size)
return malloc_db (size);
else
free_db (ptr);
return NULL;
}
int32_t dump_alloc (void)
{
int i, j;
for (j = i = 0; i < 512; ++i)
if (vptrs [i])
j++;
return j;
}
#endif

142
Libraries/WavPack/Files/compile Executable file
View file

@ -0,0 +1,142 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
scriptversion=2005-02-03.08
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand `-c -o'.
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file `INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
esac
ofile=
cfile=
eat=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we strip `-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

View file

@ -0,0 +1,62 @@
# wavpack 4.2 configure.ac
AC_INIT(wavpack, 4.2, bryant@wavpack.com)
AM_INIT_AUTOMAKE(wavpack, 4.2, bryant@wavpack.com)
AC_CONFIG_SRCDIR([pack.c])
# Check for os version
VERSION_OS=$(uname -s)
AC_DEFINE_UNQUOTED(VERSION_OS, "$VERSION_OS", [os version])
# Check for processor characteristics
AC_C_BIGENDIAN(AC_DEFINE([HIGHFIRST], [1], [big-endian machine]))
# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
# Checks for libraries.
AC_CHECK_LIB(m, log10, [], AC_MSG_ERROR(math library not found))
# Check for iconv
AC_ARG_WITH(iconv, [ --with-iconv[=DIR] Add ICONV support (on)])
if test "$with_iconv" = "no" ; then
AC_MSG_ERROR([[Sorry, you can't deactivate iconv.]])
else
if test "$with_iconv" != "yes" -a "$with_iconv" != "" ; then
CPPFLAGS="${CPPFLAGS} -I$with_iconv/include"
ICONV_LIBS="-L$with_iconv/lib"
fi
AC_CHECK_HEADER(iconv.h,
AC_MSG_CHECKING(for iconv)
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],[
iconv_t cd = iconv_open ("","");
iconv (cd, NULL, NULL, NULL, NULL);],[
AC_MSG_RESULT(yes)
WITH_ICONV=1
ICONV=""],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING(for iconv in -liconv)
_ldflags="${LDFLAGS}"
_libs="${LIBS}"
LDFLAGS="${LDFLAGS} ${ICONV_LIBS}"
LIBS="${LIBS} -liconv"
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],[
iconv_t cd = iconv_open ("","");
iconv (cd, NULL, NULL, NULL, NULL);],[
AC_MSG_RESULT(yes)
WITH_ICONV=1
ICONV_LIBS="${ICONV_LIBS} -liconv"
ICONV="${ICONV_LIBS}"],[
AC_MSG_ERROR([[Can't find iconv libraries.]])])]),
AC_MSG_ERROR([[Can't find iconv headers.]]))
fi
AC_SUBST(ICONV)
AC_SUBST(ICONV_LIBS)
AC_OUTPUT(Makefile wavpack.pc)

529
Libraries/WavPack/Files/depcomp Executable file
View file

@ -0,0 +1,529 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2005-02-09.22
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# 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, 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputing dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> $depfile
echo >> $depfile
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> $depfile
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
tmpdepfile="$stripped.u"
if test "$libtool" = yes; then
"$@" -Wc,-M
else
"$@" -M
fi
stat=$?
if test -f "$tmpdepfile"; then :
else
stripped=`echo "$stripped" | sed 's,^.*/,,'`
tmpdepfile="$stripped.u"
fi
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
if test -f "$tmpdepfile"; then
outname="$stripped.o"
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mecanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no
for arg in "$@"; do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix="`echo $object | sed 's/^.*\././'`"
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
for arg
do
case "$arg" in
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

View file

@ -0,0 +1,563 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// extra1.c
// This module handles the "extra" mode for mono files.
#include "wavpack.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
// #define EXTRA_DUMP
#ifdef DEBUG_ALLOC
#define malloc malloc_db
#define realloc realloc_db
#define free free_db
void *malloc_db (uint32_t size);
void *realloc_db (void *ptr, uint32_t size);
void free_db (void *ptr);
int32_t dump_alloc (void);
#endif
//////////////////////////////// local tables ///////////////////////////////
extern const char default_terms [], high_terms [], fast_terms [];
// #define MINMAX_WEIGHTS
#ifdef MINMAX_WEIGHTS
static int32_t min_weight, max_weight;
static int min_term, max_term;
#endif
static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_t num_samples, struct decorr_pass *dpp, int dir)
{
int m = 0;
dpp->sum_A = 0;
#ifdef MINMAX_WEIGHTS
dpp->min = dpp->max = 0;
#endif
if (dir < 0) {
out_samples += (num_samples - 1);
in_samples += (num_samples - 1);
dir = -1;
}
else
dir = 1;
if (dpp->term > MAX_TERM) {
while (num_samples--) {
int32_t left, sam_A;
if (dpp->term & 1)
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
else
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
dpp->samples_A [1] = dpp->samples_A [0];
dpp->samples_A [0] = left = in_samples [0];
left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
#endif
out_samples [0] = left;
in_samples += dir;
out_samples += dir;
}
}
else if (dpp->term > 0) {
while (num_samples--) {
int k = (m + dpp->term) & (MAX_TERM - 1);
int32_t left, sam_A;
sam_A = dpp->samples_A [m];
dpp->samples_A [k] = left = in_samples [0];
m = (m + 1) & (MAX_TERM - 1);
left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
#endif
out_samples [0] = left;
in_samples += dir;
out_samples += dir;
}
}
#ifdef MINMAX_WEIGHTS
if (dpp->term != 0) {
if (dpp->max > max_weight) { max_weight = dpp->max; max_term = dpp->term; }
if (dpp->min < min_weight) { min_weight = dpp->min; min_term = dpp->term; }
}
#endif
if (m && dpp->term > 0 && dpp->term <= MAX_TERM) {
int32_t temp_A [MAX_TERM];
int k;
memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
for (k = 0; k < MAX_TERM; k++) {
dpp->samples_A [k] = temp_A [m];
m = (m + 1) & (MAX_TERM - 1);
}
}
}
static void reverse_mono_decorr (struct decorr_pass *dpp)
{
if (dpp->term > MAX_TERM) {
int32_t sam_A;
if (dpp->term & 1)
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
else
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
dpp->samples_A [1] = dpp->samples_A [0];
dpp->samples_A [0] = sam_A;
if (dpp->term & 1)
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
else
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
dpp->samples_A [1] = sam_A;
}
else if (dpp->term > 1) {
int i = 0, j = dpp->term - 1, cnt = dpp->term / 2;
while (cnt--) {
i &= (MAX_TERM - 1);
j &= (MAX_TERM - 1);
dpp->samples_A [i] ^= dpp->samples_A [j];
dpp->samples_A [j] ^= dpp->samples_A [i];
dpp->samples_A [i++] ^= dpp->samples_A [j--];
}
CLEAR (dpp->samples_A);
}
}
static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t num_samples, struct decorr_pass *dpp)
{
int delta = dpp->delta, pre_delta, term = dpp->term;
struct decorr_pass dp;
if (delta == 7)
pre_delta = 7;
else if (delta < 2)
pre_delta = 3;
else
pre_delta = delta + 1;
CLEAR (dp);
dp.term = term;
dp.delta = pre_delta;
decorr_mono_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1);
dp.delta = delta;
reverse_mono_decorr (&dp);
memcpy (dpp->samples_A, dp.samples_A, sizeof (dp.samples_A));
dpp->weight_A = dp.weight_A;
if (delta == 0) {
dp.delta = 1;
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
dp.delta = 0;
memcpy (dp.samples_A, dpp->samples_A, sizeof (dp.samples_A));
dpp->weight_A = dp.weight_A = dp.sum_A / num_samples;
}
// if (memcmp (dpp, &dp, sizeof (dp)))
// error_line ("decorr_passes don't match, delta = %d", delta);
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
}
static void recurse_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int depth, int nterms, int delta, uint32_t input_bits, uint32_t *best_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth;
int32_t *samples, *outsamples;
uint32_t term_bits [22], bits;
if (branches < 1 || depth + 1 == nterms)
branches = 1;
CLEAR (term_bits);
samples = sampleptrs [depth];
outsamples = sampleptrs [depth + 1];
for (term = 1; term <= 18; ++term) {
if (term == 17 && branches == 1 && depth + 1 < nterms)
continue;
if (term >= 9 && term <= 16)
if (term > MAX_TERM || !(wpc->config.flags & CONFIG_HIGH_FLAG) || (wpc->config.extra_flags & EXTRA_SKIP_8TO16))
continue;
if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16))
continue;
dps [depth].term = term;
dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
bits = log2buffer (outsamples, wps->wphdr.block_samples);
if (bits < *best_bits) {
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * (depth + 1));
memcpy (sampleptrs [nterms + 1], sampleptrs [depth + 1], wps->wphdr.block_samples * 4);
}
term_bits [term + 3] = bits;
}
while (depth + 1 < nterms && branches--) {
uint32_t local_best_bits = input_bits;
int best_term = 0, i;
for (i = 0; i < 22; ++i)
if (term_bits [i] && term_bits [i] < local_best_bits) {
local_best_bits = term_bits [i];
term_bits [i] = 0;
best_term = i - 3;
}
if (!best_term)
break;
dps [depth].term = best_term;
dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
// if (log2buffer (outsamples, wps->wphdr.block_samples * 2) != local_best_bits)
// error_line ("data doesn't match!");
recurse_mono (wpc, sampleptrs, dps, depth + 1, nterms, delta, local_best_bits, best_bits);
}
}
static void delta_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int nterms, uint32_t *best_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int lower = FALSE, delta, d;
uint32_t bits;
if (wps->decorr_passes [0].term)
delta = wps->decorr_passes [0].delta;
else
return;
for (d = delta - 1; d >= 0; --d) {
int i;
if (!d && (wps->wphdr.flags & HYBRID_FLAG))
break;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
}
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
if (bits < *best_bits) {
lower = TRUE;
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
}
else
break;
}
for (d = delta + 1; !lower && d <= 7; ++d) {
int i;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
}
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
if (bits < *best_bits) {
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
}
else
break;
}
}
static void sort_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int nterms, uint32_t *best_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int reversed = TRUE;
uint32_t bits;
while (reversed) {
int ri, i;
memcpy (dps, wps->decorr_passes, sizeof (wps->decorr_passes));
reversed = FALSE;
for (ri = 0; ri < nterms && wps->decorr_passes [ri].term; ++ri) {
if (ri + 1 >= nterms || !wps->decorr_passes [ri+1].term)
break;
if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) {
decorr_mono_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]);
continue;
}
dps [ri] = wps->decorr_passes [ri+1];
dps [ri+1] = wps->decorr_passes [ri];
for (i = ri; i < nterms && wps->decorr_passes [i].term; ++i)
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
if (bits < *best_bits) {
reversed = TRUE;
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
}
else {
dps [ri] = wps->decorr_passes [ri];
dps [ri+1] = wps->decorr_passes [ri+1];
decorr_mono_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]);
}
}
}
}
#define EXTRA_ADVANCED (EXTRA_BRANCHES | EXTRA_SORT_FIRST | EXTRA_SORT_LAST | EXTRA_TRY_DELTAS)
void analyze_mono (WavpackContext *wpc, int32_t *samples)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
#ifdef EXTRA_DUMP
uint32_t bits, best_bits, default_bits, cnt;
#else
uint32_t bits, best_bits, cnt;
#endif
const char *decorr_terms = default_terms, *tp;
int32_t *sampleptrs [MAX_NTERMS+2], *lptr;
struct decorr_pass dps [MAX_NTERMS];
int nterms, i;
CLEAR (wps->decorr_passes);
cnt = wps->wphdr.block_samples;
lptr = samples;
while (cnt--)
if (*lptr++)
break;
if (cnt == (uint32_t) -1) {
scan_word (wps, samples, wps->wphdr.block_samples, -1);
wps->num_terms = 0;
return;
}
if (wpc->config.flags & CONFIG_HIGH_FLAG)
decorr_terms = high_terms;
else if (wpc->config.flags & CONFIG_FAST_FLAG)
decorr_terms = fast_terms;
for (nterms = 0, tp = decorr_terms; *tp; tp++)
if (*tp > 0)
++nterms;
if (wpc->config.extra_flags & EXTRA_TERMS)
if ((nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
nterms = MAX_NTERMS;
for (i = 0; i < nterms + 2; ++i)
sampleptrs [i] = malloc (wps->wphdr.block_samples * 4);
memcpy (sampleptrs [nterms + 1], samples, wps->wphdr.block_samples * 4);
best_bits = log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples);
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 4);
CLEAR (dps);
for (tp = decorr_terms, i = 0; *tp; tp++)
if (*tp > 0) {
dps [i].term = *tp;
dps [i].delta = 2;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
++i;
}
#ifdef EXTRA_DUMP
default_bits = bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
#else
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
#endif
if (bits < best_bits) {
best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
}
if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) {
int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING;
int32_t *rptr = sampleptrs [nterms + 1], error = 0, temp;
scan_word (wps, rptr, wps->wphdr.block_samples, -1);
cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0];
if (wps->wphdr.flags & HYBRID_SHAPE) {
while (cnt--) {
shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16;
temp = -apply_weight (shaping_weight, error);
if (new && shaping_weight < 0 && temp) {
if (temp == error)
temp = (temp < 0) ? temp + 1 : temp - 1;
lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0] + temp);
}
else
lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0]) + temp;
lptr++;
rptr++;
}
wps->dc.shaping_acc [0] -= wps->dc.shaping_delta [0] * wps->wphdr.block_samples;
}
else
while (cnt--) {
lptr [0] += nosend_word (wps, rptr [0], 0) - rptr [0];
lptr++;
rptr++;
}
memcpy (dps, wps->decorr_passes, sizeof (dps));
for (i = 0; i < nterms && dps [i].term; ++i)
decorr_mono_buffer (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i);
#ifdef EXTRA_DUMP
best_bits = default_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
#else
best_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
#endif
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
}
if (wpc->config.extra_flags & EXTRA_BRANCHES)
recurse_mono (wpc, sampleptrs, dps, 0, nterms, (int) floor (wps->delta_decay + 0.5),
log2buffer (sampleptrs [0], wps->wphdr.block_samples), &best_bits);
if (wpc->config.extra_flags & EXTRA_SORT_FIRST)
sort_mono (wpc, sampleptrs, dps, nterms, &best_bits);
if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) {
delta_mono (wpc, sampleptrs, dps, nterms, &best_bits);
if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term)
wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0;
else
wps->delta_decay = 2.0;
}
if (wpc->config.extra_flags & EXTRA_SORT_LAST)
sort_mono (wpc, sampleptrs, dps, nterms, &best_bits);
#if 0
memcpy (dps, wps->decorr_passes, sizeof (dps));
for (i = 0; i < nterms && dps [i].term; ++i)
decorr_mono_pass (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i, 1);
if (log2buffer (sampleptrs [i], wps->wphdr.block_samples) != best_bits)
error_line ("(1) samples do not match!");
if (log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples) != best_bits)
error_line ("(2) samples do not match!");
#endif
scan_word (wps, sampleptrs [nterms + 1], wps->wphdr.block_samples, -1);
#ifdef EXTRA_DUMP
if (wpc->config.extra_flags & EXTRA_DUMP_TERMS) {
char string [256], substring [20];
int i;
sprintf (string, "M: delta = %.4f%%, terms =",
((double) best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0);
for (i = 0; i < nterms; ++i) {
if (wps->decorr_passes [i].term) {
if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
sprintf (substring, " %d", wps->decorr_passes [i].term);
else
sprintf (substring, " %d->%d", wps->decorr_passes [i].term,
wps->decorr_passes [i].delta);
}
else
sprintf (substring, " *");
strcat (string, substring);
}
error_line (string);
}
#endif
for (i = 0; i < nterms; ++i)
if (!wps->decorr_passes [i].term)
break;
wps->num_terms = i;
for (i = 0; i < nterms + 2; ++i)
free (sampleptrs [i]);
#ifdef MINMAX_WEIGHTS
error_line ("weight range = %ld (%d) to %ld (%d)", min_weight, min_term, max_weight, max_term);
#endif
}

View file

@ -0,0 +1,792 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// extra2.c
// This module handles the "extra" mode for stereo files.
#include "wavpack.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
// #define EXTRA_DUMP
#ifdef DEBUG_ALLOC
#define malloc malloc_db
#define realloc realloc_db
#define free free_db
void *malloc_db (uint32_t size);
void *realloc_db (void *ptr, uint32_t size);
void free_db (void *ptr);
int32_t dump_alloc (void);
#endif
extern const char default_terms [], high_terms [], fast_terms [];
// #define MINMAX_WEIGHTS
#ifdef MINMAX_WEIGHTS
static int32_t min_weight, max_weight;
static int min_term, max_term;
#endif
static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32_t num_samples, struct decorr_pass *dpp, int dir)
{
int m = 0;
dpp->sum_A = dpp->sum_B = 0;
#ifdef MINMAX_WEIGHTS
dpp->min = dpp->max = 0;
#endif
if (dir < 0) {
out_samples += (num_samples - 1) * 2;
in_samples += (num_samples - 1) * 2;
dir = -2;
}
else
dir = 2;
if (dpp->term == 17) {
while (num_samples--) {
int32_t left, right;
int32_t sam_A, sam_B;
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
dpp->samples_A [1] = dpp->samples_A [0];
dpp->samples_A [0] = left = in_samples [0];
left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A;
out_samples [0] = left;
sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1];
dpp->samples_B [1] = dpp->samples_B [0];
dpp->samples_B [0] = right = in_samples [1];
right -= apply_weight (dpp->weight_B, sam_B);
update_weight (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_B += dpp->weight_B;
out_samples [1] = right;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
in_samples += dir;
out_samples += dir;
}
}
else if (dpp->term == 18) {
while (num_samples--) {
int32_t left, right;
int32_t sam_A, sam_B;
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
dpp->samples_A [1] = dpp->samples_A [0];
dpp->samples_A [0] = left = in_samples [0];
left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A;
out_samples [0] = left;
sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
dpp->samples_B [1] = dpp->samples_B [0];
dpp->samples_B [0] = right = in_samples [1];
right -= apply_weight (dpp->weight_B, sam_B);
update_weight (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_B += dpp->weight_B;
out_samples [1] = right;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
in_samples += dir;
out_samples += dir;
}
}
else if (dpp->term > 0) {
while (num_samples--) {
int k = (m + dpp->term) & (MAX_TERM - 1);
int32_t left, right;
int32_t sam_A, sam_B;
sam_A = dpp->samples_A [m];
dpp->samples_A [k] = left = in_samples [0];
left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A;
out_samples [0] = left;
sam_B = dpp->samples_B [m];
dpp->samples_B [k] = right = in_samples [1];
right -= apply_weight (dpp->weight_B, sam_B);
update_weight (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_B += dpp->weight_B;
out_samples [1] = right;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
in_samples += dir;
out_samples += dir;
m = (m + 1) & (MAX_TERM - 1);
}
}
else if (dpp->term == -1) {
while (num_samples--) {
int32_t left = in_samples [0];
int32_t right = in_samples [1];
int32_t sam_A = dpp->samples_A [0], sam_B = left;
dpp->samples_A [0] = right;
right -= apply_weight (dpp->weight_B, sam_B);
update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right);
left -= apply_weight (dpp->weight_A, sam_A);
update_weight_clip (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A;
dpp->sum_B += dpp->weight_B;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
out_samples [0] = left;
out_samples [1] = right;
in_samples += dir;
out_samples += dir;
}
}
else if (dpp->term == -2) {
while (num_samples--) {
int32_t left = in_samples [0];
int32_t right = in_samples [1];
int32_t sam_B = dpp->samples_B [0], sam_A = right;
dpp->samples_B [0] = left;
left -= apply_weight (dpp->weight_A, sam_A);
update_weight_clip (dpp->weight_A, dpp->delta, sam_A, left);
right -= apply_weight (dpp->weight_B, sam_B);
update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_A += dpp->weight_A;
dpp->sum_B += dpp->weight_B;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
out_samples [0] = left;
out_samples [1] = right;
in_samples += dir;
out_samples += dir;
}
}
else if (dpp->term == -3) {
while (num_samples--) {
int32_t left = in_samples [0];
int32_t right = in_samples [1];
int32_t sam_A = dpp->samples_A [0], sam_B = dpp->samples_B [0];
dpp->samples_A [0] = right;
dpp->samples_B [0] = left;
left -= apply_weight (dpp->weight_A, sam_A);
update_weight_clip (dpp->weight_A, dpp->delta, sam_A, left);
right -= apply_weight (dpp->weight_B, sam_B);
update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_A += dpp->weight_A;
dpp->sum_B += dpp->weight_B;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
out_samples [0] = left;
out_samples [1] = right;
in_samples += dir;
out_samples += dir;
}
}
#ifdef MINMAX_WEIGHTS
if (dpp->term != 0) {
if (dpp->max > max_weight) { max_weight = dpp->max; max_term = dpp->term; }
if (dpp->min < min_weight) { min_weight = dpp->min; min_term = dpp->term; }
}
#endif
if (m && dpp->term > 0 && dpp->term <= MAX_TERM) {
int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];
int k;
memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B));
for (k = 0; k < MAX_TERM; k++) {
dpp->samples_A [k] = temp_A [m];
dpp->samples_B [k] = temp_B [m];
m = (m + 1) & (MAX_TERM - 1);
}
}
}
static void reverse_decorr (struct decorr_pass *dpp)
{
if (dpp->term > MAX_TERM) {
int32_t sam_A, sam_B;
if (dpp->term & 1) {
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1];
}
else {
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
}
dpp->samples_A [1] = dpp->samples_A [0];
dpp->samples_B [1] = dpp->samples_B [0];
dpp->samples_A [0] = sam_A;
dpp->samples_B [0] = sam_B;
if (dpp->term & 1) {
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1];
}
else {
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
}
dpp->samples_A [1] = sam_A;
dpp->samples_B [1] = sam_B;
}
else if (dpp->term > 1) {
int i = 0, j = dpp->term - 1, cnt = dpp->term / 2;
while (cnt--) {
i &= (MAX_TERM - 1);
j &= (MAX_TERM - 1);
dpp->samples_A [i] ^= dpp->samples_A [j];
dpp->samples_A [j] ^= dpp->samples_A [i];
dpp->samples_A [i] ^= dpp->samples_A [j];
dpp->samples_B [i] ^= dpp->samples_B [j];
dpp->samples_B [j] ^= dpp->samples_B [i];
dpp->samples_B [i++] ^= dpp->samples_B [j--];
}
// CLEAR (dpp->samples_A);
// CLEAR (dpp->samples_B);
}
else if (dpp->term == -1) {
}
else if (dpp->term == -2) {
}
else if (dpp->term == -3) {
}
}
static void decorr_stereo_buffer (int32_t *samples, int32_t *outsamples, int32_t num_samples, struct decorr_pass *dpp)
{
int delta = dpp->delta, pre_delta;
int term = dpp->term;
struct decorr_pass dp;
if (delta == 7)
pre_delta = 7;
else if (delta < 2)
pre_delta = 3;
else
pre_delta = delta + 1;
CLEAR (dp);
dp.term = term;
dp.delta = pre_delta;
decorr_stereo_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1);
dp.delta = delta;
reverse_decorr (&dp);
memcpy (dpp->samples_A, dp.samples_A, sizeof (dp.samples_A));
memcpy (dpp->samples_B, dp.samples_B, sizeof (dp.samples_B));
dpp->weight_A = dp.weight_A;
dpp->weight_B = dp.weight_B;
if (delta == 0) {
dp.delta = 1;
decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1);
dp.delta = 0;
memcpy (dp.samples_A, dpp->samples_A, sizeof (dp.samples_A));
memcpy (dp.samples_B, dpp->samples_B, sizeof (dp.samples_B));
dpp->weight_A = dp.weight_A = dp.sum_A / num_samples;
dpp->weight_B = dp.weight_B = dp.sum_B / num_samples;
}
// if (memcmp (dpp, &dp, sizeof (dp)))
// error_line ("decorr_passes don't match, delta = %d", delta);
decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1);
}
static void recurse_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int depth, int nterms, int delta, uint32_t input_bits, uint32_t *best_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth;
int32_t *samples, *outsamples;
uint32_t term_bits [22], bits;
if (branches < 1 || depth + 1 == nterms)
branches = 1;
CLEAR (term_bits);
samples = sampleptrs [depth];
outsamples = sampleptrs [depth + 1];
for (term = -3; term <= 18; ++term) {
if (!term)
continue;
if (term == 17 && branches == 1 && depth + 1 < nterms)
continue;
if (term == -1 || term == -2)
if (!(wps->wphdr.flags & CROSS_DECORR))
continue;
if (term >= 9 && term <= 16)
if (term > MAX_TERM || !(wpc->config.flags & CONFIG_HIGH_FLAG) || (wpc->config.extra_flags & EXTRA_SKIP_8TO16))
continue;
if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16))
continue;
dps [depth].term = term;
dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
bits = log2buffer (outsamples, wps->wphdr.block_samples * 2);
if (bits < *best_bits) {
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * (depth + 1));
memcpy (sampleptrs [nterms + 1], sampleptrs [depth + 1], wps->wphdr.block_samples * 8);
}
term_bits [term + 3] = bits;
}
while (depth + 1 < nterms && branches--) {
uint32_t local_best_bits = input_bits;
int best_term = 0, i;
for (i = 0; i < 22; ++i)
if (term_bits [i] && term_bits [i] < local_best_bits) {
local_best_bits = term_bits [i];
term_bits [i] = 0;
best_term = i - 3;
}
if (!best_term)
break;
dps [depth].term = best_term;
dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
// if (log2buffer (outsamples, wps->wphdr.block_samples * 2) != local_best_bits)
// error_line ("data doesn't match!");
recurse_stereo (wpc, sampleptrs, dps, depth + 1, nterms, delta, local_best_bits, best_bits);
}
}
static void delta_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int nterms, uint32_t *best_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int lower = FALSE;
int delta, d;
uint32_t bits;
if (wps->decorr_passes [0].term)
delta = wps->decorr_passes [0].delta;
else
return;
for (d = delta - 1; d >= 0; --d) {
int i;
if (!d && (wps->wphdr.flags & HYBRID_FLAG))
break;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
}
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
if (bits < *best_bits) {
lower = TRUE;
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
}
else
break;
}
for (d = delta + 1; !lower && d <= 7; ++d) {
int i;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
}
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
if (bits < *best_bits) {
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
}
else
break;
}
}
static void sort_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int nterms, uint32_t *best_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int reversed = TRUE;
uint32_t bits;
while (reversed) {
int ri, i;
memcpy (dps, wps->decorr_passes, sizeof (wps->decorr_passes));
reversed = FALSE;
for (ri = 0; ri < nterms && wps->decorr_passes [ri].term; ++ri) {
if (ri + 1 >= nterms || !wps->decorr_passes [ri+1].term)
break;
if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) {
decorr_stereo_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]);
continue;
}
dps [ri] = wps->decorr_passes [ri+1];
dps [ri+1] = wps->decorr_passes [ri];
for (i = ri; i < nterms && wps->decorr_passes [i].term; ++i)
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
if (bits < *best_bits) {
reversed = TRUE;
*best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
}
else {
dps [ri] = wps->decorr_passes [ri];
dps [ri+1] = wps->decorr_passes [ri+1];
decorr_stereo_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]);
}
}
}
}
#define EXTRA_ADVANCED (EXTRA_BRANCHES | EXTRA_SORT_FIRST | EXTRA_SORT_LAST | EXTRA_TRY_DELTAS)
void analyze_stereo (WavpackContext *wpc, int32_t *samples)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
#ifdef EXTRA_DUMP
uint32_t bits, best_bits, default_bits, cnt;
#else
uint32_t bits, best_bits, cnt;
#endif
const char *decorr_terms = default_terms, *tp;
int32_t *sampleptrs [MAX_NTERMS+2], *lptr;
struct decorr_pass dps [MAX_NTERMS];
int nterms, i;
CLEAR (wps->decorr_passes);
cnt = wps->wphdr.block_samples * 2;
lptr = samples;
while (cnt--)
if (*lptr++)
break;
if (cnt == (uint32_t) -1) {
scan_word (wps, samples, wps->wphdr.block_samples, -1);
wps->num_terms = 0;
return;
}
if (wpc->config.flags & CONFIG_HIGH_FLAG)
decorr_terms = high_terms;
else if (wpc->config.flags & CONFIG_FAST_FLAG)
decorr_terms = fast_terms;
nterms = strlen (decorr_terms);
if (wpc->config.extra_flags & EXTRA_TERMS)
if ((nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
nterms = MAX_NTERMS;
for (i = 0; i < nterms + 2; ++i)
sampleptrs [i] = malloc (wps->wphdr.block_samples * 8);
memcpy (sampleptrs [nterms + 1], samples, wps->wphdr.block_samples * 8);
best_bits = log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples * 2);
if ((wpc->config.extra_flags & EXTRA_STEREO_MODES) || !(wps->wphdr.flags & JOINT_STEREO)) {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8);
CLEAR (dps);
for (tp = decorr_terms, i = 0; *tp;) {
if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR))
dps [i].term = *tp++;
else {
dps [i].term = -3;
tp++;
}
dps [i].delta = 2;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
++i;
}
#ifdef EXTRA_DUMP
default_bits = bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
#else
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
#endif
wps->wphdr.flags &= ~JOINT_STEREO;
if (bits < best_bits) {
best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
}
}
if ((wpc->config.extra_flags & EXTRA_STEREO_MODES) || (wps->wphdr.flags & JOINT_STEREO)) {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8);
cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0];
while (cnt--) {
lptr [1] += ((lptr [0] -= lptr [1]) >> 1);
lptr += 2;
}
CLEAR (dps);
for (tp = decorr_terms, i = 0; *tp;) {
if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR))
dps [i].term = *tp++;
else {
dps [i].term = -3;
tp++;
}
dps [i].delta = 2;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
++i;
}
#ifdef EXTRA_DUMP
default_bits = bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
#else
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
#endif
wps->wphdr.flags |= JOINT_STEREO;
if (bits < best_bits) {
best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
}
else {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8);
wps->wphdr.flags &= ~JOINT_STEREO;
}
}
if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) {
int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING;
int32_t *rptr = sampleptrs [nterms + 1], error [2], temp;
scan_word (wps, rptr, wps->wphdr.block_samples, -1);
cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0];
CLEAR (error);
if (wps->wphdr.flags & HYBRID_SHAPE) {
while (cnt--) {
shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16;
temp = -apply_weight (shaping_weight, error [0]);
if (new && shaping_weight < 0 && temp) {
if (temp == error [0])
temp = (temp < 0) ? temp + 1 : temp - 1;
lptr [0] += (error [0] = nosend_word (wps, rptr [0], 0) - rptr [0] + temp);
}
else
lptr [0] += (error [0] = nosend_word (wps, rptr [0], 0) - rptr [0]) + temp;
shaping_weight = (wps->dc.shaping_acc [1] += wps->dc.shaping_delta [1]) >> 16;
temp = -apply_weight (shaping_weight, error [1]);
if (new && shaping_weight < 0 && temp) {
if (temp == error [1])
temp = (temp < 0) ? temp + 1 : temp - 1;
lptr [1] += (error [1] = nosend_word (wps, rptr [1], 1) - rptr [1] + temp);
}
else
lptr [1] += (error [1] = nosend_word (wps, rptr [1], 1) - rptr [1]) + temp;
lptr += 2;
rptr += 2;
}
wps->dc.shaping_acc [0] -= wps->dc.shaping_delta [0] * wps->wphdr.block_samples;
wps->dc.shaping_acc [1] -= wps->dc.shaping_delta [1] * wps->wphdr.block_samples;
}
else
while (cnt--) {
lptr [0] += nosend_word (wps, rptr [0], 0) - rptr [0];
lptr [1] += nosend_word (wps, rptr [1], 1) - rptr [1];
lptr += 2;
rptr += 2;
}
memcpy (dps, wps->decorr_passes, sizeof (dps));
for (i = 0; i < nterms && dps [i].term; ++i)
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i);
#ifdef EXTRA_DUMP
best_bits = default_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
#else
best_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
#endif
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
}
if (wpc->config.extra_flags & EXTRA_BRANCHES)
recurse_stereo (wpc, sampleptrs, dps, 0, nterms, (int) floor (wps->delta_decay + 0.5),
log2buffer (sampleptrs [0], wps->wphdr.block_samples * 2), &best_bits);
if (wpc->config.extra_flags & EXTRA_SORT_FIRST)
sort_stereo (wpc, sampleptrs, dps, nterms, &best_bits);
if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) {
delta_stereo (wpc, sampleptrs, dps, nterms, &best_bits);
if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term)
wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0;
else
wps->delta_decay = 2.0;
}
if (wpc->config.extra_flags & EXTRA_SORT_LAST)
sort_stereo (wpc, sampleptrs, dps, nterms, &best_bits);
#if 0
memcpy (dps, wps->decorr_passes, sizeof (dps));
for (i = 0; i < nterms && dps [i].term; ++i)
decorr_stereo_pass (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i, 1);
if (log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2) != best_bits)
error_line ("(1) samples do not match!");
if (log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples * 2) != best_bits)
error_line ("(2) samples do not match!");
#endif
scan_word (wps, sampleptrs [nterms + 1], wps->wphdr.block_samples, -1);
#ifdef EXTRA_DUMP
if (1) {
char string [256], substring [20];
int i;
sprintf (string, "%s: delta = %.4f%%, terms =",
(wps->wphdr.flags & JOINT_STEREO) ? "JS" : "TS",
((double) best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0);
for (i = 0; i < nterms; ++i) {
if (wps->decorr_passes [i].term) {
if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
sprintf (substring, " %d", wps->decorr_passes [i].term);
else
sprintf (substring, " %d->%d", wps->decorr_passes [i].term,
wps->decorr_passes [i].delta);
}
else
sprintf (substring, " *");
strcat (string, substring);
}
error_line (string);
}
#endif
for (i = 0; i < nterms; ++i)
if (!wps->decorr_passes [i].term)
break;
wps->num_terms = i;
for (i = 0; i < nterms + 2; ++i)
free (sampleptrs [i]);
#ifdef MINMAX_WEIGHTS
error_line ("weight range = %ld (%d) to %ld (%d)", min_weight, min_term, max_weight, max_term);
#endif
}

View file

@ -0,0 +1,371 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// float.c
#include "wavpack.h"
#include <stdlib.h>
#ifdef DEBUG_ALLOC
#define malloc malloc_db
#define realloc realloc_db
#define free free_db
void *malloc_db (uint32_t size);
void *realloc_db (void *ptr, uint32_t size);
void free_db (void *ptr);
int32_t dump_alloc (void);
#endif
#ifdef PACK
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
char *byteptr;
byteptr = wpmd->data = malloc (4);
wpmd->id = ID_FLOAT_INFO;
*byteptr++ = wps->float_flags;
*byteptr++ = wps->float_shift;
*byteptr++ = wps->float_max_exp;
*byteptr++ = wps->float_norm_exp;
wpmd->byte_length = byteptr - (char *) wpmd->data;
}
int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
{
int32_t shifted_ones = 0, shifted_zeros = 0, shifted_both = 0;
int32_t false_zeros = 0, neg_zeros = 0;
uint32_t ordata = 0, crc = 0xffffffff;
int max_exp = 0, shift_count;
int32_t count, value;
f32 *dp;
wps->float_shift = wps->float_flags = 0;
for (dp = values, count = num_values; count--; dp++) {
crc = crc * 27 + dp->mantissa * 9 + dp->exponent * 3 + dp->sign;
if (dp->exponent > max_exp && dp->exponent < 255)
max_exp = dp->exponent;
}
wps->crc_x = crc;
for (dp = values, count = num_values; count--; dp++) {
if (dp->exponent == 255) {
wps->float_flags |= FLOAT_EXCEPTIONS;
value = 0x1000000;
shift_count = 0;
}
else if (dp->exponent) {
shift_count = max_exp - dp->exponent;
value = 0x800000 + dp->mantissa;
}
else {
shift_count = max_exp ? max_exp - 1 : 0;
value = dp->mantissa;
// if (dp->mantissa)
// denormals++;
}
if (shift_count < 25)
value >>= shift_count;
else
value = 0;
if (!value) {
if (dp->exponent || dp->mantissa)
++false_zeros;
else if (dp->sign)
++neg_zeros;
}
else if (shift_count) {
int32_t mask = (1 << shift_count) - 1;
if (!(dp->mantissa & mask))
shifted_zeros++;
else if ((dp->mantissa & mask) == mask)
shifted_ones++;
else
shifted_both++;
}
ordata |= value;
* (int32_t *) dp = (dp->sign) ? -value : value;
}
wps->float_max_exp = max_exp;
if (shifted_both)
wps->float_flags |= FLOAT_SHIFT_SENT;
else if (shifted_ones && !shifted_zeros)
wps->float_flags |= FLOAT_SHIFT_ONES;
else if (shifted_ones && shifted_zeros)
wps->float_flags |= FLOAT_SHIFT_SAME;
else if (ordata && !(ordata & 1)) {
while (!(ordata & 1)) {
wps->float_shift++;
ordata >>= 1;
}
for (dp = values, count = num_values; count--; dp++)
* (int32_t *) dp >>= wps->float_shift;
}
wps->wphdr.flags &= ~MAG_MASK;
while (ordata) {
wps->wphdr.flags += 1 << MAG_LSB;
ordata >>= 1;
}
if (false_zeros || neg_zeros)
wps->float_flags |= FLOAT_ZEROS_SENT;
if (neg_zeros)
wps->float_flags |= FLOAT_NEG_ZEROS;
// error_line ("samples = %d, max exp = %d, pre-shift = %d, denormals = %d",
// num_values, max_exp, wps->float_shift, denormals);
// if (wps->float_flags & FLOAT_EXCEPTIONS)
// error_line ("exceptions!");
// error_line ("shifted ones/zeros/both = %d/%d/%d, true/neg/false zeros = %d/%d/%d",
// shifted_ones, shifted_zeros, shifted_both, true_zeros, neg_zeros, false_zeros);
return wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME);
}
void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
{
int max_exp = wps->float_max_exp;
int32_t count, value, shift_count;
f32 *dp;
for (dp = values, count = num_values; count--; dp++) {
if (dp->exponent == 255) {
if (dp->mantissa) {
putbit_1 (&wps->wvxbits);
putbits (dp->mantissa, 23, &wps->wvxbits);
}
else {
putbit_0 (&wps->wvxbits);
}
value = 0x1000000;
shift_count = 0;
}
else if (dp->exponent) {
shift_count = max_exp - dp->exponent;
value = 0x800000 + dp->mantissa;
}
else {
shift_count = max_exp ? max_exp - 1 : 0;
value = dp->mantissa;
}
if (shift_count < 25)
value >>= shift_count;
else
value = 0;
if (!value) {
if (wps->float_flags & FLOAT_ZEROS_SENT) {
if (dp->exponent || dp->mantissa) {
putbit_1 (&wps->wvxbits);
putbits (dp->mantissa, 23, &wps->wvxbits);
if (max_exp >= 25) {
putbits (dp->exponent, 8, &wps->wvxbits);
}
putbit (dp->sign, &wps->wvxbits);
}
else {
putbit_0 (&wps->wvxbits);
if (wps->float_flags & FLOAT_NEG_ZEROS)
putbit (dp->sign, &wps->wvxbits);
}
}
}
else if (shift_count) {
if (wps->float_flags & FLOAT_SHIFT_SENT) {
int32_t data = dp->mantissa & ((1 << shift_count) - 1);
putbits (data, shift_count, &wps->wvxbits);
}
else if (wps->float_flags & FLOAT_SHIFT_SAME) {
putbit (dp->mantissa & 1, &wps->wvxbits);
}
}
}
}
#endif
#if defined(UNPACK) || defined(INFO_ONLY)
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
char *byteptr = wpmd->data;
if (bytecnt != 4)
return FALSE;
wps->float_flags = *byteptr++;
wps->float_shift = *byteptr++;
wps->float_max_exp = *byteptr++;
wps->float_norm_exp = *byteptr;
return TRUE;
}
#endif
#ifdef UNPACK
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values);
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
{
uint32_t crc = wps->crc_x;
if (!bs_is_open (&wps->wvxbits)) {
float_values_nowvx (wps, values, num_values);
return;
}
while (num_values--) {
int shift_count = 0, exp = wps->float_max_exp;
f32 outval = { 0, 0, 0 };
uint32_t temp;
if (*values == 0) {
if (wps->float_flags & FLOAT_ZEROS_SENT) {
if (getbit (&wps->wvxbits)) {
getbits (&temp, 23, &wps->wvxbits);
outval.mantissa = temp;
if (exp >= 25) {
getbits (&temp, 8, &wps->wvxbits);
outval.exponent = temp;
}
outval.sign = getbit (&wps->wvxbits);
}
else if (wps->float_flags & FLOAT_NEG_ZEROS)
outval.sign = getbit (&wps->wvxbits);
}
}
else {
*values <<= wps->float_shift;
if (*values < 0) {
*values = -*values;
outval.sign = 1;
}
if (*values == 0x1000000) {
if (getbit (&wps->wvxbits)) {
getbits (&temp, 23, &wps->wvxbits);
outval.mantissa = temp;
}
outval.exponent = 255;
}
else {
if (exp)
while (!(*values & 0x800000) && --exp) {
shift_count++;
*values <<= 1;
}
if (shift_count) {
if ((wps->float_flags & FLOAT_SHIFT_ONES) ||
((wps->float_flags & FLOAT_SHIFT_SAME) && getbit (&wps->wvxbits)))
*values |= ((1 << shift_count) - 1);
else if (wps->float_flags & FLOAT_SHIFT_SENT) {
getbits (&temp, shift_count, &wps->wvxbits);
*values |= temp & ((1 << shift_count) - 1);
}
}
outval.mantissa = *values;
outval.exponent = exp;
}
}
crc = crc * 27 + outval.mantissa * 9 + outval.exponent * 3 + outval.sign;
* (f32 *) values++ = outval;
}
wps->crc_x = crc;
}
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values)
{
while (num_values--) {
int shift_count = 0, exp = wps->float_max_exp;
f32 outval = { 0, 0, 0 };
if (*values) {
*values <<= wps->float_shift;
if (*values < 0) {
*values = -*values;
outval.sign = 1;
}
if (*values >= 0x1000000) {
while (*values & 0xf000000) {
*values >>= 1;
++exp;
}
}
else if (exp) {
while (!(*values & 0x800000) && --exp) {
shift_count++;
*values <<= 1;
}
if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
*values |= ((1 << shift_count) - 1);
}
outval.mantissa = *values;
outval.exponent = exp;
}
* (f32 *) values++ = outval;
}
}
void float_normalize (int32_t *values, int32_t num_values, int delta_exp)
{
f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
int exp;
if (!delta_exp)
return;
while (num_values--) {
if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0)
*fvalues = fzero;
else if (exp == 255 || (exp += delta_exp) >= 255) {
fvalues->exponent = 255;
fvalues->mantissa = 0;
}
else
fvalues->exponent = exp;
fvalues++;
}
}
#endif

View file

@ -0,0 +1,96 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
WavPack 4.0 File / Block Format
-------------------------------
A WavPack 4.0 file consists of a series of WavPack audio blocks. It may also
contain tags and other information, but these must be outside the blocks
(either before, in-between, or after) and are ignored for the purpose of
unpacking audio data. The WavPack blocks are easy to identify by their
unique header data, and by looking in the header it is very easy to
determine the total size of the block, both in physical bytes and compressed
samples. There are no seek tables.
The blocks (or frames, if you prefer) are completely independent in that they
can be decoded to mono or stereo audio all by themselves. A single function
is provided to convert a whole block into its corresponding audio data.
Similarly, a function is provided to convert a block of audio samples into
a finished WavPack block. These all work in memory; disk I/O is handled
outside. It is also possible to decode or encode blocks in smaller increments
if it is important to distribute CPU load more evenly over time. The blocks may
also be decoded without reading the whole block into memory, although this
would only be important for hardware decoding.
The blocks may contain any number of samples, either stereo or mono. Obviously,
putting more samples in each block is more efficient, but they are reasonably
efficient down to even a thousand samples. I have set the max size to 1 MB for
the whole block, but this is arbitrary. The blocks may be lossless or lossy
(currently the lossy modes are basically CBR, but I am planning a quality
based VBR version also).
For multichannel audio, the data is divided into some number of stereo and mono
streams and multiplexed into separate blocks. Because blocks are independent
there can be a mix of sampling rates, but all the streams must be sliced at
the same point in time which is a multiple of all the sampling rates. The
metadata contains source information (like front, center, rear, etc.).
Correction files (.wvc) have an identical structure to the main file (.wv) and
there is a one-to-one correspondence between main file blocks that contain
audio and their correction file match (blocks that do not contain audio do
not exist in the correction file). The only difference in the headers of
main blocks and correction blocks is the CRC value, although it is easy to
tell the blocks apart by looking at the metadata ids.
Here is the 32-byte header at the front of every block:
typedef struct {
char ckID [4]; // "wvpk"
long ckSize; // size of entire frame (minus 8, of course)
short version; // 0x403 for now
uchar track_no; // track number (0 if not used, like now)
uchar index_no; // track sub-index (0 if not used, like now)
ulong total_samples; // for entire file (-1 if unknown)
ulong block_index; // index of first sample in block (to file begin)
ulong block_samples; // # samples in this block
ulong flags; // various flags for id and decoding
ulong crc; // crc for actual decoded data
} WavpackHeader;
The "flags" field contains information for decoding the block along with some
general information including sample size and format, hybrid/lossless,
mono/stereo and sampling rate. This structure is stored "little-endian".
Following the 32-byte header to the end of the block are a series of "metadata"
sub-blocks. These may from 2 bytes long to the size of the entire block and are
extremely easy to parse (even without knowing what they mean). Currently these
mostly contain extra information needed to decode the audio, but may also
contain user information. The only non-audio information I currently have
implemented is a copy of the original wave RIFF header (or trailer if present),
and the MD5 checksums, but there is plenty of flexibility here. For example,
these metadata blocks could store cuesheets, artist/title information,
replaygain values, even pictures or lyrics. The final metadata sub-blocks are
the actual audio bitstreams, which have ids for standard audio (wvbits),
correction data (wvcbits), and a special extension for large integer and
floating-point data (wvxbits).
The format of the metadata is:
uchar id; // mask meaning
// ---- -------
// 0x1f metadata function
// 0x20 decoder need not understand metadata
// 0x40 actual data byte length is 1 less
// 0x80 large block (> 255 words)
uchar word_size; // small block: data size in words (padded)
or...
uchar word_size [3]; // large block: data size in words (padded,
little-endian)
ushort data [word_size]; // data, padded to an even # of bytes

View file

@ -0,0 +1,323 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2005-02-02.21
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
chmodcmd="$chmodprog 0755"
chowncmd=
chgrpcmd=
stripcmd=
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=
dst=
dir_arg=
dstarg=
no_target_directory=
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
"
while test -n "$1"; do
case $1 in
-c) shift
continue;;
-d) dir_arg=true
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
--help) echo "$usage"; exit $?;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t) dstarg=$2
shift
shift
continue;;
-T) no_target_directory=true
shift
continue;;
--version) echo "$0 $scriptversion"; exit $?;;
*) # When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
test -n "$dir_arg$dstarg" && break
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
shift # fnord
fi
shift # arg
dstarg=$arg
done
break;;
esac
done
if test -z "$1"; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
for src
do
# Protect names starting with `-'.
case $src in
-*) src=./$src ;;
esac
if test -n "$dir_arg"; then
dst=$src
src=
if test -d "$dst"; then
mkdircmd=:
chmodcmd=
else
mkdircmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dstarg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dstarg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst ;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dstarg: Is a directory" >&2
exit 1
fi
dst=$dst/`basename "$src"`
fi
fi
# This sed command emulates the dirname command.
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# Skip lots of stat calls in the usual case.
if test ! -d "$dstdir"; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
shift
IFS=$oIFS
pathcomp=
while test $# -ne 0 ; do
pathcomp=$pathcomp$1
shift
if test ! -d "$pathcomp"; then
$mkdirprog "$pathcomp"
# mkdir can fail with a `File exist' error in case several
# install-sh are creating the directory concurrently. This
# is OK.
test -d "$pathcomp" || exit
fi
pathcomp=$pathcomp/
done
fi
if test -n "$dir_arg"; then
$doit $mkdircmd "$dst" \
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
else
dstfile=`basename "$dst"`
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
trap '(exit $?); exit' 1 2 13 15
# Copy the file name to the temp name.
$doit $cpprog "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
# Now rename the file to the real destination.
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|| {
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
if test -f "$dstdir/$dstfile"; then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|| {
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit 1
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
}
}
fi || { (exit 1); exit 1; }
done
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit 0
}
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

View file

@ -0,0 +1,25 @@
Copyright (c) 1998 - 2005 Conifer Software
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Conifer Software nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,263 @@
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/* Brutally hacked by John Walker back from ANSI C to K&R (no
prototypes) to maintain the tradition that Netfone will compile
with Sun's original "cc". */
#include <memory.h> /* for memcpy() */
#include "md5.h"
#ifdef sgi
#define HIGHFIRST
#endif
#ifdef sun
#define HIGHFIRST
#endif
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
#else
/*
* Note: this code is harmless on little-endian machines.
*/
void byteReverse(buf, longs)
unsigned char *buf; unsigned longs;
{
uint32 t;
do {
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32 *) buf = t;
buf += 4;
} while (--longs);
}
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(ctx)
struct MD5Context *ctx;
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(ctx, buf, len)
struct MD5Context *ctx; unsigned char *buf; unsigned len;
{
uint32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(digest, ctx)
unsigned char digest[16]; struct MD5Context *ctx;
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((uint32 *) ctx->in)[14] = ctx->bits[0];
((uint32 *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (uint32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(buf, in)
uint32 buf[4]; uint32 in[16];
{
register uint32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}

View file

@ -0,0 +1,26 @@
#ifndef MD5_H
#define MD5_H
#if defined (__alpha__) || defined (__x86_64__)
typedef unsigned int uint32;
#else
typedef unsigned long uint32;
#endif
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
extern void MD5Init();
extern void MD5Update();
extern void MD5Final();
extern void MD5Transform();
/*
* This is needed to make RSAREF happy on some MS-DOS compilers.
*/
typedef struct MD5Context MD5_CTX;
#endif /* !MD5_H */

View file

@ -0,0 +1,310 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// metadata.c
// This module handles the metadata structure introduced in WavPack 4.0
#include "wavpack.h"
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG_ALLOC
#define malloc malloc_db
#define realloc realloc_db
#define free free_db
void *malloc_db (uint32_t size);
void *realloc_db (void *ptr, uint32_t size);
void free_db (void *ptr);
int32_t dump_alloc (void);
#endif
#if defined(UNPACK) || defined(INFO_ONLY)
int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr)
{
WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
uchar *buffend = blockbuff + wphdr->ckSize + 8;
if (buffend - *buffptr < 2)
return FALSE;
wpmd->id = *(*buffptr)++;
wpmd->byte_length = *(*buffptr)++ << 1;
if (wpmd->id & ID_LARGE) {
wpmd->id &= ~ID_LARGE;
if (buffend - *buffptr < 2)
return FALSE;
wpmd->byte_length += *(*buffptr)++ << 9;
wpmd->byte_length += *(*buffptr)++ << 17;
}
if (wpmd->id & ID_ODD_SIZE) {
wpmd->id &= ~ID_ODD_SIZE;
wpmd->byte_length--;
}
if (wpmd->byte_length) {
if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
wpmd->data = NULL;
return FALSE;
}
wpmd->data = *buffptr;
(*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
}
else
wpmd->data = NULL;
return TRUE;
}
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
switch (wpmd->id) {
case ID_DUMMY:
return TRUE;
case ID_DECORR_TERMS:
return read_decorr_terms (wps, wpmd);
case ID_DECORR_WEIGHTS:
return read_decorr_weights (wps, wpmd);
case ID_DECORR_SAMPLES:
return read_decorr_samples (wps, wpmd);
case ID_ENTROPY_VARS:
return read_entropy_vars (wps, wpmd);
case ID_HYBRID_PROFILE:
return read_hybrid_profile (wps, wpmd);
case ID_SHAPING_WEIGHTS:
return read_shaping_info (wps, wpmd);
case ID_FLOAT_INFO:
return read_float_info (wps, wpmd);
case ID_INT32_INFO:
return read_int32_info (wps, wpmd);
case ID_CHANNEL_INFO:
return read_channel_info (wpc, wpmd);
case ID_CONFIG_BLOCK:
return read_config_info (wpc, wpmd);
case ID_WV_BITSTREAM:
return init_wv_bitstream (wps, wpmd);
case ID_WVC_BITSTREAM:
return init_wvc_bitstream (wps, wpmd);
case ID_WVX_BITSTREAM:
return init_wvx_bitstream (wps, wpmd);
case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
return read_wrapper_data (wpc, wpmd);
case ID_MD5_CHECKSUM:
if (wpmd->byte_length == 16) {
memcpy (wpc->config.md5_checksum, wpmd->data, 16);
wpc->config.flags |= CONFIG_MD5_CHECKSUM;
wpc->config.md5_read = 1;
}
return TRUE;
default:
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
}
}
#endif
#ifdef PACK
int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end)
{
uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
if (wpmd->byte_length & 1)
((char *) wpmd->data) [wpmd->byte_length] = 0;
mdsize += (wpmd->byte_length > 510) ? 4 : 2;
buffer_start += wphdr->ckSize + 8;
if (buffer_start + mdsize >= buffer_end)
return FALSE;
buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
buffer_start [1] = (wpmd->byte_length + 1) >> 1;
if (wpmd->byte_length > 510) {
buffer_start [0] |= ID_LARGE;
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
}
if (wpmd->data && wpmd->byte_length) {
if (wpmd->byte_length > 510) {
buffer_start [0] |= ID_LARGE;
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
memcpy (buffer_start + 4, wpmd->data, mdsize - 4);
}
else
memcpy (buffer_start + 2, wpmd->data, mdsize - 2);
}
wphdr->ckSize += mdsize;
return TRUE;
}
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id)
{
WavpackMetadata *mdp;
uchar *src = data;
while (bcount) {
if (wpc->metacount) {
uint32_t bc = bcount;
mdp = wpc->metadata + wpc->metacount - 1;
if (mdp->id == id) {
if (wpc->metabytes + bcount > 1000000)
bc = 1000000 - wpc->metabytes;
mdp->data = realloc (mdp->data, mdp->byte_length + bc);
memcpy ((char *) mdp->data + mdp->byte_length, src, bc);
mdp->byte_length += bc;
wpc->metabytes += bc;
bcount -= bc;
src += bc;
if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc))
return FALSE;
}
}
if (bcount) {
wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata));
mdp = wpc->metadata + wpc->metacount++;
mdp->byte_length = 0;
mdp->data = NULL;
mdp->id = id;
}
}
return TRUE;
}
static char *write_metadata (WavpackMetadata *wpmd, char *outdata)
{
uchar id = wpmd->id, wordlen [3];
wordlen [0] = (wpmd->byte_length + 1) >> 1;
wordlen [1] = (wpmd->byte_length + 1) >> 9;
wordlen [2] = (wpmd->byte_length + 1) >> 17;
if (wpmd->byte_length & 1) {
// ((char *) wpmd->data) [wpmd->byte_length] = 0;
id |= ID_ODD_SIZE;
}
if (wordlen [1] || wordlen [2])
id |= ID_LARGE;
*outdata++ = id;
*outdata++ = wordlen [0];
if (id & ID_LARGE) {
*outdata++ = wordlen [1];
*outdata++ = wordlen [2];
}
if (wpmd->data && wpmd->byte_length) {
memcpy (outdata, wpmd->data, wpmd->byte_length);
outdata += wpmd->byte_length;
if (wpmd->byte_length & 1)
*outdata++ = 0;
}
return outdata;
}
int write_metadata_block (WavpackContext *wpc)
{
char *block_buff, *block_ptr;
WavpackHeader *wphdr;
if (wpc->metacount) {
int metacount = wpc->metacount, block_size = sizeof (WavpackHeader);
WavpackMetadata *wpmdp = wpc->metadata;
while (metacount--) {
block_size += wpmdp->byte_length + (wpmdp->byte_length & 1);
block_size += (wpmdp->byte_length > 510) ? 4 : 2;
wpmdp++;
}
wphdr = (WavpackHeader *) (block_buff = malloc (block_size));
CLEAR (*wphdr);
memcpy (wphdr->ckID, "wvpk", 4);
wphdr->total_samples = wpc->total_samples;
wphdr->version = 0x403;
wphdr->ckSize = block_size - 8;
wphdr->block_samples = 0;
block_ptr = (char *)(wphdr + 1);
wpmdp = wpc->metadata;
while (wpc->metacount) {
block_ptr = write_metadata (wpmdp, block_ptr);
wpc->metabytes -= wpmdp->byte_length;
free_metadata (wpmdp++);
wpc->metacount--;
}
free (wpc->metadata);
wpc->metadata = NULL;
native_to_little_endian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
free (block_buff);
strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
return FALSE;
}
free (block_buff);
}
return TRUE;
}
#endif
void free_metadata (WavpackMetadata *wpmd)
{
if (wpmd->data) {
free (wpmd->data);
wpmd->data = NULL;
}
}

357
Libraries/WavPack/Files/missing Executable file
View file

@ -0,0 +1,357 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2005-02-08.22
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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, 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
esac
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program).
case "$1" in
lex|yacc)
# Not GNU programs, they don't have --version.
;;
tar)
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
exit 1
fi
;;
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
fi
if [ -f "$file" ]; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit 1
fi
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
touch $file
;;
tar)
shift
# We have already tried tar in the generic part.
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
fi
firstarg="$1"
if shift; then
case "$firstarg" in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
;;
esac
case "$firstarg" in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
;;
esac
fi
echo 1>&2 "\
WARNING: I can't seem to be able to run \`tar' with the given arguments.
You may want to install GNU tar or Free paxutils, or check the
command line arguments."
exit 1
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// wavpack3.h
// This header file contains all the additional definitions required for
// decoding old (versions 1, 2 & 3) WavPack files.
typedef struct {
ushort FormatTag, NumChannels;
uint32_t SampleRate, BytesPerSecond;
ushort BlockAlign, BitsPerSample;
} WaveHeader3;
#define WaveHeader3Format "SSLLSS"
typedef struct {
char ckID [4];
int32_t ckSize;
short version;
short bits; // added for version 2.00
short flags, shift; // added for version 3.00
int32_t total_samples, crc, crc2;
char extension [4], extra_bc, extras [3];
} WavpackHeader3;
#define WavpackHeader3Format "4LSSSSLLL4L"
// these flags added for version 3
#undef MONO_FLAG // these definitions changed for WavPack 4.0
#undef CROSS_DECORR
#undef JOINT_STEREO
#define MONO_FLAG 1 // not stereo
#define FAST_FLAG 2 // non-adaptive predictor and stereo mode
#define RAW_FLAG 4 // raw mode (no .wav header)
#define CALC_NOISE 8 // calc noise in lossy mode (no longer stored)
#define HIGH_FLAG 0x10 // high quality mode (all modes)
#define BYTES_3 0x20 // files have 3-byte samples
#define OVER_20 0x40 // samples are over 20 bits
#define WVC_FLAG 0x80 // create/use .wvc (no longer stored)
#define LOSSY_SHAPE 0x100 // noise shape (lossy mode only)
#define VERY_FAST_FLAG 0x200 // double fast (no longer stored)
#define NEW_HIGH_FLAG 0x400 // new high quality mode (lossless only)
#define CANCEL_EXTREME 0x800 // cancel EXTREME_DECORR
#define CROSS_DECORR 0x1000 // decorrelate chans (with EXTREME_DECORR flag)
#define NEW_DECORR_FLAG 0x2000 // new high-mode decorrelator
#define JOINT_STEREO 0x4000 // joint stereo (lossy and high lossless)
#define EXTREME_DECORR 0x8000 // extra decorrelation (+ enables other flags)
#define STORED_FLAGS 0xfd77 // these are only flags that affect unpacking
#define NOT_STORED_FLAGS (~STORED_FLAGS & 0xffff)
// BitStream stuff (bits.c)
typedef struct bs3 {
void (*wrap)(struct bs3 *bs);
uchar *buf, *end, *ptr;
uint32_t bufsiz, fpos, sr;
stream_reader *reader;
int error, bc;
void *id;
} Bitstream3;
#define K_DEPTH 3
#define MAX_NTERMS3 18
typedef struct {
WavpackHeader3 wphdr;
Bitstream3 wvbits, wvcbits;
uint32_t sample_index;
int num_terms;
#ifdef SEEKING
struct index_point {
char saved;
uint32_t sample_index;
} index_points [256];
uchar *unpack_data;
uint32_t unpack_size;
#endif
struct {
int32_t sum_level, left_level, right_level, diff_level;
int last_extra_bits, extra_bits_count, m;
int32_t error [2], crc;
int32_t sample [2] [2];
int weight [2] [1];
} dc;
struct decorr_pass decorr_passes [MAX_NTERMS3];
struct {
uint index [2], k_value [2], ave_k [2];
uint32_t zeros_acc, ave_level [K_DEPTH] [2];
} w1;
struct { int last_dbits [2], last_delta_sign [2], bit_limit; } w2;
struct { int ave_dbits [2], bit_limit; } w3;
struct {
uint32_t fast_level [2], slow_level [2];
int bits_acc [2], bitrate;
} w4;
} WavpackStream3;

View file

@ -0,0 +1,640 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// utils.c
// This module provides general purpose utilities for the WavPack command-line
// utilities and the self-extraction module.
#if defined(WIN32)
#include <windows.h>
#include <io.h>
#include <conio.h>
#elif defined(__GNUC__)
#include <glob.h>
#endif
#ifndef WIN32
#include <locale.h>
#include <iconv.h>
#endif
#include <sys/stat.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "wavpack.h"
#ifdef WIN32
int copy_timestamp (const char *src_filename, const char *dst_filename)
{
FILETIME last_modified;
HANDLE src, dst;
int res = TRUE;
if (*src_filename == '-' || *dst_filename == '-')
return res;
src = CreateFile (src_filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
dst = CreateFile (dst_filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (src == INVALID_HANDLE_VALUE || dst == INVALID_HANDLE_VALUE ||
!GetFileTime (src, NULL, NULL, &last_modified) ||
!SetFileTime (dst, NULL, NULL, &last_modified))
res = FALSE;
if (src != INVALID_HANDLE_VALUE)
CloseHandle (src);
if (dst != INVALID_HANDLE_VALUE)
CloseHandle (dst);
return res;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// This function parses a filename (with or without full path) and returns //
// a pointer to the extension (including the "."). If no extension is found //
// then NULL is returned. Extensions with more than 3 letters don't count. //
//////////////////////////////////////////////////////////////////////////////
#if defined(WIN32)
static int is_second_byte (char *filespec, char *pos);
char *filespec_ext (char *filespec)
{
char *cp = filespec + strlen (filespec);
LANGID langid = GetSystemDefaultLangID ();
while (--cp >= filespec) {
if (langid == 0x411 && is_second_byte (filespec, cp))
--cp;
if (*cp == '\\' || *cp == ':')
return NULL;
if (*cp == '.') {
if (strlen (cp) > 1 && strlen (cp) <= 4)
return cp;
else
return NULL;
}
}
return NULL;
}
#else
char *filespec_ext (char *filespec)
{
char *cp = filespec + strlen (filespec);
while (--cp >= filespec) {
if (*cp == '\\' || *cp == ':')
return NULL;
if (*cp == '.') {
if (strlen (cp) > 1 && strlen (cp) <= 4)
return cp;
else
return NULL;
}
}
return NULL;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// This function determines if the specified filespec is a valid pathname. //
// If not, NULL is returned. If it is in the format of a pathname, then the //
// original pointer is returned. If the format is ambiguous, then a lookup //
// is performed to determine if it is in fact a valid path, and if so a "\" //
// is appended so that the pathname can be used and the original pointer is //
// returned. //
//////////////////////////////////////////////////////////////////////////////
#if defined(__GNUC__) && !defined(WIN32)
char *filespec_path (char *filespec)
{
char *cp = filespec + strlen (filespec);
glob_t globs;
struct stat fstats;
if (cp == filespec || filespec_wild (filespec))
return NULL;
if (*--cp == '\\' || *cp == ':')
return filespec;
if (*cp == '.' && cp == filespec)
return strcat (filespec, "\\");
if (glob (filespec, GLOB_MARK|GLOB_NOSORT, NULL, &globs) == 0 &&
globs.gl_pathc > 0)
{
/* test if the file is a directory */
if (stat(globs.gl_pathv[0], &fstats) == 0 && (fstats.st_mode & S_IFDIR)) {
globfree(&globs);
filespec[0] = '\0';
return strcat (filespec, globs.gl_pathv[0]);
}
}
globfree(&globs);
return NULL;
}
#else
char *filespec_path (char *filespec)
{
char *cp = filespec + strlen (filespec);
LANGID langid = GetSystemDefaultLangID ();
struct _finddata_t finddata;
int32_t file;
if (cp == filespec || filespec_wild (filespec))
return NULL;
--cp;
if (langid == 0x411 && is_second_byte (filespec, cp))
--cp;
if (*cp == '\\' || *cp == ':')
return filespec;
if (*cp == '.' && cp == filespec)
return strcat (filespec, "\\");
if ((file = _findfirst (filespec, &finddata)) != -1L &&
(finddata.attrib & _A_SUBDIR)) {
_findclose (file);
return strcat (filespec, "\\");
}
if (file != -1L)
_findclose(file);
return NULL;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// This function returns non-NULL if the specified filename spec has any //
// wildcard characters. //
//////////////////////////////////////////////////////////////////////////////
char *filespec_wild (char *filespec)
{
return strpbrk (filespec, "*?");
}
//////////////////////////////////////////////////////////////////////////////
// This function parses a filename (with or without full path) and returns //
// a pointer to the actual filename, or NULL if no filename can be found. //
//////////////////////////////////////////////////////////////////////////////
#if defined(WIN32)
char *filespec_name (char *filespec)
{
char *cp = filespec + strlen (filespec);
LANGID langid = GetSystemDefaultLangID ();
while (--cp >= filespec) {
if (langid == 0x411 && is_second_byte (filespec, cp))
--cp;
if (*cp == '\\' || *cp == ':')
break;
}
if (strlen (cp + 1))
return cp + 1;
else
return NULL;
}
#else
char *filespec_name (char *filespec)
{
char *cp = filespec + strlen (filespec);
while (--cp >= filespec)
if (*cp == '\\' || *cp == ':')
break;
if (strlen (cp + 1))
return cp + 1;
else
return NULL;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// This function returns TRUE if "pos" is pointing to the second byte of a //
// double-byte character in the string "filespec" which is assumed to be //
// shift-JIS. //
//////////////////////////////////////////////////////////////////////////////
#if defined(WIN32)
static int is_second_byte (char *filespec, char *pos)
{
uchar *cp = pos;
while (cp > filespec && ((cp [-1] >= 0x81 && cp [-1] <= 0x9f) ||
(cp [-1] >= 0xe0 && cp [-1] <= 0xfc)))
cp--;
return ((int) pos - (int) cp) & 1;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// This function allows the user to type 'y', 'n', or 'a' (with Enter) in //
// response to a system query. The return value is the key typed as //
// lowercase (regardless of the typed case). //
//////////////////////////////////////////////////////////////////////////////
static int waiting_input;
char yna (void)
{
char choice = 0;
int key;
waiting_input = 1;
while (1) {
#if defined(WIN32)
key = getch ();
#else
key = fgetc(stdin);
#endif
if (key == 3) {
fprintf (stderr, "^C\n");
exit (1);
}
else if (key == '\r' || key == '\n') {
if (choice) {
fprintf (stderr, "\r\n");
break;
}
else
fprintf (stderr, "%c", 7);
}
else if (key == 'Y' || key == 'y') {
fprintf (stderr, "%c\b", key);
choice = 'y';
}
else if (key == 'N' || key == 'n') {
fprintf (stderr, "%c\b", key);
choice = 'n';
}
else if (key == 'A' || key == 'a') {
fprintf (stderr, "%c\b", key);
choice = 'a';
}
else
fprintf (stderr, "%c", 7);
}
waiting_input = 0;
return choice;
}
//////////////////////////////////////////////////////////////////////////////
// Display the specified message on the console through stderr. Note that //
// the cursor may start anywhere in the line and all text already on the //
// line is erased. A terminating newline is not needed and function works //
// with printf strings and args. //
//////////////////////////////////////////////////////////////////////////////
void error_line (char *error, ...)
{
char error_msg [512];
va_list argptr;
error_msg [0] = '\r';
va_start (argptr, error);
vsprintf (error_msg + 1, error, argptr);
va_end (argptr);
fputs (error_msg, stderr);
finish_line ();
#if 0
{
FILE *error_log = fopen ("c:\\wavpack.log", "a+");
if (error_log) {
fputs (error_msg + 1, error_log);
fputc ('\n', error_log);
fclose (error_log);
}
}
#endif
}
//////////////////////////////////////////////////////////////////////////////
// Function to intercept ^C or ^Break typed at the console. //
//////////////////////////////////////////////////////////////////////////////
#if defined(WIN32)
static int break_flag;
BOOL WINAPI ctrl_handler (DWORD ctrl)
{
if (ctrl == CTRL_C_EVENT) {
break_flag = TRUE;
return TRUE;
}
if (ctrl == CTRL_BREAK_EVENT) {
if (waiting_input) {
#ifdef __BORLANDC__
fprintf (stderr, "^C\n");
#endif
return FALSE;
}
else {
break_flag = TRUE;
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
// Function to initialize console for intercepting ^C and ^Break. //
//////////////////////////////////////////////////////////////////////////////
void setup_break (void)
{
HANDLE hConIn = GetStdHandle (STD_INPUT_HANDLE);
SetConsoleMode (hConIn, ENABLE_PROCESSED_INPUT);
FlushConsoleInputBuffer (hConIn);
SetConsoleCtrlHandler (ctrl_handler, TRUE);
break_flag = 0;
}
//////////////////////////////////////////////////////////////////////////////
// Function to determine whether ^C or ^Break has been issued by user. //
//////////////////////////////////////////////////////////////////////////////
int check_break (void)
{
return break_flag;
}
//////////////////////////////////////////////////////////////////////////////
// Function to clear the stderr console to the end of the current line (and //
// go to the beginning next line). //
//////////////////////////////////////////////////////////////////////////////
void finish_line (void)
{
HANDLE hConIn = GetStdHandle (STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO coninfo;
if (hConIn && GetConsoleScreenBufferInfo (hConIn, &coninfo)) {
char spaces = coninfo.dwSize.X - coninfo.dwCursorPosition.X;
while (spaces--)
fputc (' ', stderr);
}
else
fputc ('\n', stderr);
}
#else
//////////////////////////////////////////////////////////////////////////////
// Function to clear the stderr console to the end of the current line (and //
// go to the beginning next line). //
//////////////////////////////////////////////////////////////////////////////
void finish_line (void)
{
/* char spaces = 1;
while (spaces--)
putc (' ', stderr);
else*/
fputc ('\n', stderr);
}
//////////////////////////////////////////////////////////////////////////////
// Function to initialize console for intercepting ^C and ^Break. //
//////////////////////////////////////////////////////////////////////////////
void setup_break (void)
{
}
//////////////////////////////////////////////////////////////////////////////
// Function to determine whether ^C or ^Break has been issued by user. //
//////////////////////////////////////////////////////////////////////////////
int check_break (void)
{
return 0;
}
#endif
//////////////////////////// File I/O Wrapper ////////////////////////////////
int DoReadFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToRead, uint32_t *lpNumberOfBytesRead)
{
uint32_t bcount;
*lpNumberOfBytesRead = 0;
while (nNumberOfBytesToRead) {
bcount = fread ((uchar *) lpBuffer + *lpNumberOfBytesRead, 1, nNumberOfBytesToRead, hFile);
if (bcount) {
*lpNumberOfBytesRead += bcount;
nNumberOfBytesToRead -= bcount;
}
else
break;
}
return !ferror (hFile);
}
int DoWriteFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToWrite, uint32_t *lpNumberOfBytesWritten)
{
uint32_t bcount;
*lpNumberOfBytesWritten = 0;
while (nNumberOfBytesToWrite) {
bcount = fwrite ((uchar *) lpBuffer + *lpNumberOfBytesWritten, 1, nNumberOfBytesToWrite, hFile);
if (bcount) {
*lpNumberOfBytesWritten += bcount;
nNumberOfBytesToWrite -= bcount;
}
else
break;
}
return !ferror (hFile);
}
uint32_t DoGetFileSize (FILE *hFile)
{
struct stat statbuf;
if (!hFile || fstat (fileno (hFile), &statbuf) || !(statbuf.st_mode & S_IFREG))
return 0;
return statbuf.st_size;
}
uint32_t DoGetFilePosition (FILE *hFile)
{
return ftell (hFile);
}
int DoSetFilePositionAbsolute (FILE *hFile, uint32_t pos)
{
return fseek (hFile, pos, SEEK_SET);
}
int DoSetFilePositionRelative (FILE *hFile, int32_t pos, int mode)
{
return fseek (hFile, pos, mode);
}
// if ungetc() is not available, a seek of -1 is fine also because we do not
// change the byte read.
int DoUngetc (int c, FILE *hFile)
{
return ungetc (c, hFile);
}
int DoCloseHandle (FILE *hFile)
{
return hFile ? !fclose (hFile) : 0;
}
int DoTruncateFile (FILE *hFile)
{
if (hFile) {
fflush (hFile);
#if defined(WIN32)
return !chsize (fileno (hFile), 0);
#else
return !ftruncate(fileno (hFile), 0);
#endif
}
return 0;
}
int DoDeleteFile (char *filename)
{
return !remove (filename);
}
// Convert the Unicode wide-format string into a UTF-8 string using no more
// than the specified buffer length. The wide-format string must be NULL
// terminated and the resulting string will be NULL terminated. The actual
// number of characters converted (not counting terminator) is returned, which
// may be less than the number of characters in the wide string if the buffer
// length is exceeded.
static int WideCharToUTF8 (const ushort *Wide, uchar *pUTF8, int len)
{
const ushort *pWide = Wide;
int outndx = 0;
while (*pWide) {
if (*pWide < 0x80 && outndx + 1 < len)
pUTF8 [outndx++] = (uchar) *pWide++;
else if (*pWide < 0x800 && outndx + 2 < len) {
pUTF8 [outndx++] = (uchar) (0xc0 | ((*pWide >> 6) & 0x1f));
pUTF8 [outndx++] = (uchar) (0x80 | (*pWide++ & 0x3f));
}
else if (outndx + 3 < len) {
pUTF8 [outndx++] = (uchar) (0xe0 | ((*pWide >> 12) & 0xf));
pUTF8 [outndx++] = (uchar) (0x80 | ((*pWide >> 6) & 0x3f));
pUTF8 [outndx++] = (uchar) (0x80 | (*pWide++ & 0x3f));
}
else
break;
}
pUTF8 [outndx] = 0;
return pWide - Wide;
}
// Convert a Ansi string into its Unicode UTF-8 format equivalent. The
// conversion is done in-place so the maximum length of the string buffer must
// be specified because the string may become longer or shorter. If the
// resulting string will not fit in the specified buffer size then it is
// truncated.
void AnsiToUTF8 (char *string, int len)
{
int max_chars = strlen (string);
#if defined(WIN32)
ushort *temp = (ushort *) malloc ((max_chars + 1) * 2);
MultiByteToWideChar (CP_ACP, 0, string, -1, temp, max_chars + 1);
WideCharToUTF8 (temp, (uchar *) string, len);
#else
char *temp = malloc (len);
// memset(temp, 0, len);
char *outp = temp;
const char *inp = string;
size_t insize = max_chars;
size_t outsize = len - 1;
int err = 0;
char *old_locale;
memset(temp, 0, len);
old_locale = setlocale (LC_CTYPE, "");
iconv_t converter = iconv_open ("UTF-8", "");
err = iconv (converter, &inp, &insize, &outp, &outsize);
iconv_close (converter);
setlocale (LC_CTYPE, old_locale);
if (err == -1) {
free(temp);
return;
}
memmove (string, temp, len);
#endif
free (temp);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,656 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// wavpack.h
#ifndef WAVPACK_H
#define WAVPACK_H
#if defined(WIN32)
#define FASTCALL __fastcall
#else
#define FASTCALL
#define SetConsoleTitle(x)
#endif
#include <sys/types.h>
// This header file contains all the definitions required by WavPack.
#if defined(_WIN32) && !defined(__MINGW32__)
#include <stdlib.h>
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
typedef float float32_t;
#else
#include <inttypes.h>
#endif
typedef unsigned char uchar;
#if !defined(__GNUC__) || defined(WIN32)
typedef unsigned short ushort;
typedef unsigned int uint;
#endif
#ifndef PATH_MAX
#ifdef MAX_PATH
#define PATH_MAX MAX_PATH
#elif defined (MAXPATHLEN)
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
// This structure is used to access the individual fields of 32-bit ieee
// floating point numbers. This will not be compatible with compilers that
// allocate bit fields from the most significant bits, although I'm not sure
// how common that is.
typedef struct {
unsigned mantissa : 23;
unsigned exponent : 8;
unsigned sign : 1;
} f32;
#include <stdio.h>
#define FALSE 0
#define TRUE 1
#if defined(WIN32)
#undef VERSION_OS
#define VERSION_OS "Win32"
#endif
#define VERSION_STR "4.2 "
#define DATE_STR "2005-04-02"
// ID3v1 and APEv2 TAG formats (may occur at the end of WavPack files)
typedef struct {
uchar tag_id [3], title [30], artist [30], album [30];
uchar year [4], comment [30], genre;
} ID3_Tag;
typedef struct {
char ID [8];
int32_t version, length, item_count, flags;
char res [8];
} APE_Tag_Hdr;
#define APE_Tag_Hdr_Format "8LLLL"
typedef struct {
ID3_Tag id3_tag;
APE_Tag_Hdr ape_tag_hdr;
char *ape_tag_data;
} M_Tag;
// RIFF / wav header formats (these occur at the beginning of both wav files
// and pre-4.0 WavPack files that are not in the "raw" mode)
typedef struct {
char ckID [4];
uint32_t ckSize;
char formType [4];
} RiffChunkHeader;
typedef struct {
char ckID [4];
uint32_t ckSize;
} ChunkHeader;
#define ChunkHeaderFormat "4L"
typedef struct {
ushort FormatTag, NumChannels;
uint32_t SampleRate, BytesPerSecond;
ushort BlockAlign, BitsPerSample;
ushort cbSize, ValidBitsPerSample;
int32_t ChannelMask;
ushort SubFormat;
char GUID [14];
} WaveHeader;
#define WaveHeaderFormat "SSLLSSSSLS"
////////////////////////////// WavPack Header /////////////////////////////////
// Note that this is the ONLY structure that is written to (or read from)
// WavPack 4.0 files, and is the preamble to every block in both the .wv
// and .wvc files.
typedef struct {
char ckID [4];
uint32_t ckSize;
short version;
uchar track_no, index_no;
uint32_t total_samples, block_index, block_samples, flags, crc;
} WavpackHeader;
#define WavpackHeaderFormat "4LS2LLLLL"
// or-values for "flags"
#define BYTES_STORED 3 // 1-4 bytes/sample
#define MONO_FLAG 4 // not stereo
#define HYBRID_FLAG 8 // hybrid mode
#define JOINT_STEREO 0x10 // joint stereo
#define CROSS_DECORR 0x20 // no-delay cross decorrelation
#define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
#define FLOAT_DATA 0x80 // ieee 32-bit floating point data
#define INT32_DATA 0x100 // special extended int handling
#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
#define INITIAL_BLOCK 0x800 // initial block of multichannel segment
#define FINAL_BLOCK 0x1000 // final block of multichannel segment
#define SHIFT_LSB 13
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
#define MAG_LSB 18
#define MAG_MASK (0x1fL << MAG_LSB)
#define SRATE_LSB 23
#define SRATE_MASK (0xfL << SRATE_LSB)
#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
#define UNKNOWN_FLAGS 0xC0000000 // also reserved, but refuse decode if
// encountered
//////////////////////////// WavPack Metadata /////////////////////////////////
// This is an internal representation of metadata.
typedef struct {
int32_t byte_length;
void *data;
uchar id;
} WavpackMetadata;
#define ID_OPTIONAL_DATA 0x20
#define ID_ODD_SIZE 0x40
#define ID_LARGE 0x80
#define ID_DUMMY 0x0
#define ID_ENCODER_INFO 0x1
#define ID_DECORR_TERMS 0x2
#define ID_DECORR_WEIGHTS 0x3
#define ID_DECORR_SAMPLES 0x4
#define ID_ENTROPY_VARS 0x5
#define ID_HYBRID_PROFILE 0x6
#define ID_SHAPING_WEIGHTS 0x7
#define ID_FLOAT_INFO 0x8
#define ID_INT32_INFO 0x9
#define ID_WV_BITSTREAM 0xa
#define ID_WVC_BITSTREAM 0xb
#define ID_WVX_BITSTREAM 0xc
#define ID_CHANNEL_INFO 0xd
#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1)
#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2)
#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3)
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
///////////////////////// WavPack Configuration ///////////////////////////////
// This internal structure is used during encode to provide configuration to
// the encoding engine and during decoding to provide fle information back to
// the higher level functions. Not all fields are used in both modes.
typedef struct {
float bitrate, shaping_weight;
int bits_per_sample, bytes_per_sample;
int qmode, flags, xmode, num_channels, float_norm_exp;
int32_t block_samples, extra_flags, sample_rate, channel_mask;
uchar md5_checksum [16], md5_read;
int num_tag_strings;
char **tag_strings;
} WavpackConfig;
#define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample
#define CONFIG_MONO_FLAG 4 // not stereo
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
#define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
#define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data
#define CONFIG_ADOBE_MODE 0x100 // "adobe" mode for 32-bit floats
#define CONFIG_FAST_FLAG 0x200 // fast mode
#define CONFIG_VERY_FAST_FLAG 0x400 // double fast
#define CONFIG_HIGH_FLAG 0x800 // high quality mode
#define CONFIG_VERY_HIGH_FLAG 0x1000 // double high (not used yet)
#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
#define CONFIG_AUTO_SHAPING 0x4000 // automatic noise shaping
#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified
#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified
#define CONFIG_COPY_TIME 0x20000 // copy file-time from source
#define CONFIG_CREATE_EXE 0x40000 // create executable
#define CONFIG_CREATE_WVC 0x80000 // create correction file
#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
#define CONFIG_QUALITY_MODE 0x200000 // psychoacoustic quality mode
#define CONFIG_RAW_FLAG 0x400000 // raw mode (not implemented yet)
#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
#define CONFIG_LOSSY_MODE 0x1000000 // obsolete (for information)
#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
#define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature
#define CONFIG_QUIET_MODE 0x10000000 // don't report progress %
#define CONFIG_IGNORE_LENGTH 0x20000000 // ignore length in wav header
#define EXTRA_SCAN_ONLY 1
#define EXTRA_STEREO_MODES 2
//#define EXTRA_CHECK_TERMS 4
#define EXTRA_TRY_DELTAS 8
#define EXTRA_ADJUST_DELTAS 16
#define EXTRA_SORT_FIRST 32
#define EXTRA_BRANCHES 0x1c0
#define EXTRA_SKIP_8TO16 512
#define EXTRA_TERMS 0x3c00
#define EXTRA_DUMP_TERMS 16384
#define EXTRA_SORT_LAST 32768
//////////////////////////////// WavPack Stream ///////////////////////////////
// This internal structure contains everything required to handle a WavPack
// "stream", which is defined as a stereo or mono stream of audio samples. For
// multichannel audio several of these would be required. Each stream contains
// pointers to hold a complete allocated block of WavPack data, although it's
// possible to decode WavPack blocks without buffering an entire block.
typedef struct bs {
uchar *buf, *end, *ptr;
void (*wrap)(struct bs *bs);
int error, bc;
uint32_t sr;
} Bitstream;
#define MAX_STREAMS 8
#define MAX_NTERMS 16
#define MAX_TERM 8
struct decorr_pass {
int term, delta, weight_A, weight_B;
int32_t samples_A [MAX_TERM], samples_B [MAX_TERM];
int32_t aweight_A, aweight_B;
#ifdef PACK
int32_t sum_A, sum_B, min, max;
#endif
};
typedef struct {
WavpackHeader wphdr;
uchar *blockbuff, *blockend;
uchar *block2buff, *block2end;
int32_t *sample_buffer;
uint32_t sample_index, crc, crc_x, crc_wvx;
Bitstream wvbits, wvcbits, wvxbits;
int bits, num_terms, mute_error;
float delta_decay;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
uchar float_flags, float_shift, float_max_exp, float_norm_exp;
struct {
int32_t shaping_acc [2], shaping_delta [2], error [2];
double noise_sum, noise_ave, noise_max;
} dc;
struct decorr_pass decorr_passes [MAX_NTERMS];
struct {
uint32_t bitrate_delta [2], bitrate_acc [2];
uint32_t median [3] [2], slow_level [2], error_limit [2];
uint32_t pend_data, holding_one, zeros_acc;
int holding_zero, pend_count;
} w;
} WavpackStream;
// flags for float_flags:
#define FLOAT_SHIFT_ONES 1 // bits left-shifted into float = '1'
#define FLOAT_SHIFT_SAME 2 // bits left-shifted into float are the same
#define FLOAT_SHIFT_SENT 4 // bits shifted into float are sent literally
#define FLOAT_ZEROS_SENT 8 // "zeros" are not all real zeros
#define FLOAT_NEG_ZEROS 0x10 // contains negative zeros
#define FLOAT_EXCEPTIONS 0x20 // contains exceptions (inf, nan, etc.)
/////////////////////////////// WavPack Context ///////////////////////////////
// This internal structure holds everything required to encode or decode WavPack
// files. It is recommended that direct access to this structure be minimized
// and the provided utilities used instead.
typedef struct {
int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
uint32_t (*get_pos)(void *id);
int (*set_pos_abs)(void *id, uint32_t pos);
int (*set_pos_rel)(void *id, int32_t delta, int mode);
int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(void *id);
int (*can_seek)(void *id);
} stream_reader;
typedef int (*blockout)(void *id, void *data, int32_t bcount);
typedef struct {
WavpackConfig config;
WavpackMetadata *metadata;
uint32_t metabytes;
int metacount;
uchar *wrapper_data;
uint32_t wrapper_bytes;
blockout blockout;
void *wv_out, *wvc_out;
stream_reader *reader;
void *wv_in, *wvc_in;
uint32_t filelen, file2len, filepos, file2pos, total_samples, crc_errors, first_flags;
int wvc_flag, open_flags, norm_offset, reduced_channels, lossy_blocks, close_files;
int block_samples, max_samples, acc_samples;
M_Tag m_tag;
int current_stream, num_streams;
WavpackStream *streams [8];
void *stream3;
char error_message [80];
} WavpackContext;
//////////////////////// function prototypes and macros //////////////////////
#define CLEAR(destin) memset (&destin, 0, sizeof (destin));
// these macros implement the weight application and update operations
// that are at the heart of the decorrelation loops
#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
#define apply_weight_f(weight, sample) (((((sample & 0xffff) * weight) >> 9) + \
(((sample & ~0xffff) >> 9) * weight) + 1) >> 1)
#if 1 // PERFCOND
#define apply_weight(weight, sample) (sample != (short) sample ? \
apply_weight_f (weight, sample) : apply_weight_i (weight, sample))
#else
#define apply_weight(weight, sample) ((int32_t)((weight * (int64_t) sample + 512) >> 10))
#endif
#if 1 // PERFCOND
#define update_weight(weight, delta, source, result) \
if (source && result) weight -= ((((source ^ result) >> 30) & 2) - 1) * delta;
#else
#define update_weight(weight, delta, source, result) \
if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta);
#endif
#define update_weight_d1(weight, delta, source, result) \
if (source && result) weight -= (((source ^ result) >> 30) & 2) - 1;
#define update_weight_d2(weight, delta, source, result) \
if (source && result) weight -= (((source ^ result) >> 29) & 4) - 2;
#define update_weight_clip(weight, delta, source, result) \
if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
weight = weight < 0 ? -1024 : 1024;
#define update_weight_clip_d1(weight, delta, source, result) \
if (source && result && abs (weight -= (((source ^ result) >> 30) & 2) - 1) > 1024) \
weight = weight < 0 ? -1024 : 1024;
#define update_weight_clip_d2(weight, delta, source, result) \
if (source && result && abs (weight -= (((source ^ result) >> 29) & 4) - 2) > 1024) \
weight = weight < 0 ? -1024 : 1024;
// bits.c
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end);
void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end);
uint32_t bs_close_read (Bitstream *bs);
uint32_t bs_close_write (Bitstream *bs);
int DoReadFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToRead, uint32_t *lpNumberOfBytesRead);
int DoWriteFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToWrite, uint32_t *lpNumberOfBytesWritten);
uint32_t DoGetFileSize (FILE *hFile), DoGetFilePosition (FILE *hFile);
int DoSetFilePositionRelative (FILE *hFile, int32_t pos, int mode);
int DoSetFilePositionAbsolute (FILE *hFile, uint32_t pos);
int DoUngetc (int c, FILE *hFile), DoDeleteFile (char *filename);
int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile);
#define bs_is_open(bs) ((bs)->ptr != NULL)
#define getbit(bs) ( \
(((bs)->bc) ? \
((bs)->bc--, (bs)->sr & 1) : \
(((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = 7, ((bs)->sr = *((bs)->ptr)) & 1) \
) ? \
((bs)->sr >>= 1, 1) : \
((bs)->sr >>= 1, 0) \
)
#define getbits(value, nbits, bs) { \
while ((nbits) > (bs)->bc) { \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
(bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \
(bs)->bc += 8; \
} \
*(value) = (bs)->sr; \
(bs)->sr >>= (nbits); \
(bs)->bc -= (nbits); \
}
#define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \
if (++((bs)->bc) == 8) { \
*((bs)->ptr) = (bs)->sr; \
(bs)->sr = (bs)->bc = 0; \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
}}
#define putbit_0(bs) { \
if (++((bs)->bc) == 8) { \
*((bs)->ptr) = (bs)->sr; \
(bs)->sr = (bs)->bc = 0; \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
}}
#define putbit_1(bs) { (bs)->sr |= (1 << (bs)->bc); \
if (++((bs)->bc) == 8) { \
*((bs)->ptr) = (bs)->sr; \
(bs)->sr = (bs)->bc = 0; \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
}}
#define putbits(value, nbits, bs) { \
(bs)->sr |= (int32_t)(value) << (bs)->bc; \
if (((bs)->bc += (nbits)) >= 8) \
do { \
*((bs)->ptr) = (bs)->sr; \
(bs)->sr >>= 8; \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
} while (((bs)->bc -= 8) >= 8); \
}
void little_endian_to_native (void *data, char *format);
void native_to_little_endian (void *data, char *format);
// pack.c
void pack_init (WavpackContext *wpc);
int pack_block (WavpackContext *wpc, int32_t *buffer);
double pack_noise (WavpackContext *wpc, double *peak);
// unpack.c
int unpack_init (WavpackContext *wpc);
int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd);
int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd);
int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd);
int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd);
int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
int check_crc_error (WavpackContext *wpc);
// unpack3.c
WavpackContext *open_file3 (WavpackContext *wpc, char *error);
int32_t unpack_samples3 (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
int seek_sample3 (WavpackContext *wpc, uint32_t desired_index);
uint32_t get_sample_index3 (WavpackContext *wpc);
void free_stream3 (WavpackContext *wpc);
int get_version3 (WavpackContext *wpc);
// utils.c
int copy_timestamp (const char *src_filename, const char *dst_filename);
char *filespec_ext (char *filespec), *filespec_path (char *filespec);
char *filespec_name (char *filespec), *filespec_wild (char *filespec);
void error_line (char *error, ...), finish_line (void);
void setup_break (void);
int check_break (void);
char yna (void);
void AnsiToUTF8 (char *string, int len);
#define FN_FIT(fn) ((strlen (fn) > 30) ? filespec_name (fn) : fn)
// metadata.c stuff
int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr);
int write_metadata_block (WavpackContext *wpc);
int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end);
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id);
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
void free_metadata (WavpackMetadata *wpmd);
// words.c stuff
void init_words (WavpackStream *wps);
void word_set_bitrate (WavpackStream *wps);
void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
int32_t FASTCALL send_word (WavpackStream *wps, int32_t value, int chan);
void FASTCALL send_word_lossless (WavpackStream *wps, int32_t value, int chan);
int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction);
int32_t FASTCALL get_word_lossless (WavpackStream *wps, int chan);
void flush_word (WavpackStream *wps);
int32_t nosend_word (WavpackStream *wps, int32_t value, int chan);
void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir);
int log2s (int32_t value);
int32_t exp2s (int log);
uint32_t log2buffer (int32_t *samples, uint32_t num_samples);
char store_weight (int weight);
int restore_weight (char weight);
#define WORD_EOF (1L << 31)
// float.c
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values);
void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values);
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values);
void float_normalize (int32_t *values, int32_t num_values, int delta_exp);
// analyze?.c
void analyze_stereo (WavpackContext *wpc, int32_t *samples);
void analyze_mono (WavpackContext *wpc, int32_t *samples);
// wputils.c
WavpackContext *WavpackOpenFileInputEx (stream_reader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset);
#define OPEN_WVC 0x1 // open/read "correction" file
#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file)
#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF)
#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix)
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
// w/o regard to header file position info
int WavpackGetMode (WavpackContext *wpc);
#define MODE_WVC 0x1
#define MODE_LOSSLESS 0x2
#define MODE_HYBRID 0x4
#define MODE_FLOAT 0x8
#define MODE_VALID_TAG 0x10
#define MODE_HIGH 0x20
#define MODE_FAST 0x40
#define MODE_EXTRA 0x80
#define MODE_APETAG 0x100
#define MODE_SFX 0x200
int WavpackGetVersion (WavpackContext *wpc);
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
uint32_t WavpackGetSampleIndex (WavpackContext *wpc);
int WavpackGetNumErrors (WavpackContext *wpc);
int WavpackLossyBlocks (WavpackContext *wpc);
int WavpackSeekSample (WavpackContext *wpc, uint32_t sample);
WavpackContext *WavpackCloseFile (WavpackContext *wpc);
uint32_t WavpackGetSampleRate (WavpackContext *wpc);
int WavpackGetBitsPerSample (WavpackContext *wpc);
int WavpackGetBytesPerSample (WavpackContext *wpc);
int WavpackGetNumChannels (WavpackContext *wpc);
int WavpackGetReducedChannels (WavpackContext *wpc);
int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]);
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
uchar *WavpackGetWrapperData (WavpackContext *wpc);
void WavpackFreeWrapper (WavpackContext *wpc);
double WavpackGetProgress (WavpackContext *wpc);
uint32_t WavpackGetFileSize (WavpackContext *wpc);
double WavpackGetRatio (WavpackContext *wpc);
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
double WavpackGetInstantBitrate (WavpackContext *wpc);
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value);
int WavpackWriteTag (WavpackContext *wpc);
WavpackContext *WavpackOpenFileOutput (blockout blockout, void *wv_id, void *wvc_id);
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]);
int WavpackPackInit (WavpackContext *wpc);
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
int WavpackFlushSamples (WavpackContext *wpc);
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
void *WavpackGetWrapperLocation (void *first_block);
#endif

View file

@ -0,0 +1,11 @@
prefix=@prefix@
libdir=${prefix}/lib
includedir=${prefix}/include
Name: wavpack
Description: wavpack library
Version: @PACKAGE_VERSION@
Requires:
Conflicts:
Libs: -L${libdir} -lwavpack @ICONV@
Cflags: -I${includedir} -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,163 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// wputils.h
#ifndef WPUTILS_H
#define WPUTILS_H
// This header file contains all the definitions required to use the
// functions in "wputils.c" to read and write WavPack files and streams.
#include <sys/types.h>
#if defined(_WIN32) && !defined(__MINGW32__)
#include <stdlib.h>
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
typedef float float32_t;
#else
#include <inttypes.h>
#endif
typedef unsigned char uchar;
#if !defined(__GNUC__) || defined(WIN32)
typedef unsigned short ushort;
typedef unsigned int uint;
#endif
///////////////////////// WavPack Configuration ///////////////////////////////
// This external structure is used during encode to provide configuration to
// the encoding engine and during decoding to provide fle information back to
// the higher level functions. Not all fields are used in both modes.
typedef struct {
float bitrate, shaping_weight;
int bits_per_sample, bytes_per_sample;
int qmode, flags, xmode, num_channels, float_norm_exp;
int32_t block_samples, extra_flags, sample_rate, channel_mask;
uchar md5_checksum [16], md5_read;
int num_tag_strings;
char **tag_strings;
} WavpackConfig;
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
#define CONFIG_FAST_FLAG 0x200 // fast mode
#define CONFIG_HIGH_FLAG 0x800 // high quality mode
#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified
#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified
#define CONFIG_CREATE_WVC 0x80000 // create correction file
#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
////////////// Callbacks used for reading & writing WavPack streams //////////
typedef struct {
int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
uint32_t (*get_pos)(void *id);
int (*set_pos_abs)(void *id, uint32_t pos);
int (*set_pos_rel)(void *id, int32_t delta, int mode);
int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(void *id);
int (*can_seek)(void *id);
} stream_reader;
typedef int (*blockout)(void *id, void *data, int32_t bcount);
//////////////////////// function prototypes and macros //////////////////////
typedef void WavpackContext;
#ifdef __cplusplus
extern "C" {
#endif
WavpackContext *WavpackOpenFileInputEx (stream_reader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset);
#define OPEN_WVC 0x1 // open/read "correction" file
#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file)
#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF)
#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix)
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
// w/o regard to header file position info
int WavpackGetMode (WavpackContext *wpc);
#define MODE_WVC 0x1
#define MODE_LOSSLESS 0x2
#define MODE_HYBRID 0x4
#define MODE_FLOAT 0x8
#define MODE_VALID_TAG 0x10
#define MODE_HIGH 0x20
#define MODE_FAST 0x40
#define MODE_EXTRA 0x80
#define MODE_APETAG 0x100
#define MODE_SFX 0x200
int WavpackGetVersion (WavpackContext *wpc);
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
uint32_t WavpackGetSampleIndex (WavpackContext *wpc);
int WavpackGetNumErrors (WavpackContext *wpc);
int WavpackLossyBlocks (WavpackContext *wpc);
int WavpackSeekSample (WavpackContext *wpc, uint32_t sample);
WavpackContext *WavpackCloseFile (WavpackContext *wpc);
uint32_t WavpackGetSampleRate (WavpackContext *wpc);
int WavpackGetBitsPerSample (WavpackContext *wpc);
int WavpackGetBytesPerSample (WavpackContext *wpc);
int WavpackGetNumChannels (WavpackContext *wpc);
int WavpackGetReducedChannels (WavpackContext *wpc);
int WavpackGetFloatNormExp (WavpackContext *wpc);
int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]);
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
uchar *WavpackGetWrapperData (WavpackContext *wpc);
void WavpackFreeWrapper (WavpackContext *wpc);
double WavpackGetProgress (WavpackContext *wpc);
uint32_t WavpackGetFileSize (WavpackContext *wpc);
double WavpackGetRatio (WavpackContext *wpc);
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
double WavpackGetInstantBitrate (WavpackContext *wpc);
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value);
int WavpackWriteTag (WavpackContext *wpc);
WavpackContext *WavpackOpenFileOutput (blockout blockout, void *wv_id, void *wvc_id);
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]);
int WavpackPackInit (WavpackContext *wpc);
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
int WavpackFlushSamples (WavpackContext *wpc);
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
void *WavpackGetWrapperLocation (void *first_block);
// this function is not actually in wputils.c, but is generally useful
void float_normalize (int32_t *values, int32_t num_values, int delta_exp);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,926 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2005 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// wvunpack.c
// This is the main module for the WavPack command-line decompressor.
#if defined(WIN32)
#include <windows.h>
#include <io.h>
#else
#include <sys/stat.h>
#include <sys/param.h>
#if defined (__GNUC__)
#include <unistd.h>
#include <glob.h>
#endif
#endif
#ifdef __BORLANDC__
#include <dir.h>
#elif defined(__GNUC__) && !defined(WIN32)
#include <sys/time.h>
#else
#include <sys/timeb.h>
#endif
#include <math.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include "wavpack.h"
#include "md5.h"
#ifdef DEBUG_ALLOC
#define malloc malloc_db
#define realloc realloc_db
#define free free_db
void *malloc_db (uint32_t size);
void *realloc_db (void *ptr, uint32_t size);
void free_db (void *ptr);
int32_t dump_alloc (void);
static char *strdup (const char *s)
{ char *d = malloc (strlen (s) + 1); return strcpy (d, s); }
#endif
///////////////////////////// local variable storage //////////////////////////
static const char *sign_on = "\n"
" WVUNPACK Hybrid Lossless Wavefile Decompressor %s Version %s %s\n"
" Copyright (c) 1998 - 2005 Conifer Software. All Rights Reserved.\n\n";
static const char *usage =
" Usage: WVUNPACK [-options] [@]infile[.wv]|- [[@]outfile[.wav]|outpath|-]\n"
" (infile may contain wildcards: ?,*)\n\n"
" Options: -d = delete source file if successful (use with caution!)\n"
" -i = ignore .wvc file (forces hybrid lossy decompression)\n"
" -m = calculate and display MD5 signature; verify if lossless\n"
" -q = quiet (keep console output to a minimum)\n"
" -r = force raw audio decode (skip RIFF headers & trailers)\n"
" -s = display summary information only to stdout (no decode)\n"
#if defined (WIN32)
" -t = copy input file's time stamp to output file(s)\n"
#endif
" -v = verify source data only (no output file created)\n"
" -y = yes to overwrite warning (use with caution!)\n\n"
" Web: Visit www.wavpack.com for latest version and info\n";
static char overwrite_all = 0, delete_source = 0, raw_decode = 0, summary = 0,
ignore_wvc = 0, quiet_mode = 0, calc_md5 = 0, copy_time = 0;
static int num_files, file_index, outbuf_k;
/////////////////////////// local function declarations ///////////////////////
static int unpack_file (char *infilename, char *outfilename);
static void display_progress (double file_progress);
#define NO_ERROR 0L
#define SOFT_ERROR 1
#define HARD_ERROR 2
//////////////////////////////////////////////////////////////////////////////
// The "main" function for the command-line WavPack decompressor. //
//////////////////////////////////////////////////////////////////////////////
int main (argc, argv) int argc; char **argv;
{
int verify_only = 0, usage_error = 0, filelist = 0, add_extension = 0;
char *infilename = NULL, *outfilename = NULL;
char outpath, **matches = NULL;
int result, i;
#ifdef __BORLANDC__
struct ffblk ffblk;
#elif defined(WIN32)
struct _finddata_t _finddata_t;
#else
glob_t globs;
struct stat fstats;
#endif
// loop through command-line arguments
while (--argc) {
#if defined (WIN32)
if ((**++argv == '-' || **argv == '/') && (*argv)[1])
#else
if ((**++argv == '-') && (*argv)[1])
#endif
while (*++*argv)
switch (**argv) {
case 'Y': case 'y':
overwrite_all = 1;
break;
case 'D': case 'd':
delete_source = 1;
break;
#if defined (WIN32)
case 'T': case 't':
copy_time = 1;
break;
#endif
case 'V': case 'v':
verify_only = 1;
break;
case 'S': case 's':
summary = 1;
break;
case 'K': case 'k':
outbuf_k = strtol (++*argv, argv, 10);
--*argv;
break;
case 'M': case 'm':
calc_md5 = 1;
break;
case 'R': case 'r':
raw_decode = 1;
break;
case 'Q': case 'q':
quiet_mode = 1;
break;
case 'I': case 'i':
ignore_wvc = 1;
break;
default:
error_line ("illegal option: %c !", **argv);
usage_error = 1;
}
else {
if (!infilename) {
infilename = malloc (strlen (*argv) + PATH_MAX);
strcpy (infilename, *argv);
}
else if (!outfilename) {
outfilename = malloc (strlen (*argv) + PATH_MAX);
strcpy (outfilename, *argv);
}
else {
error_line ("extra unknown argument: %s !", *argv);
usage_error = 1;
}
}
}
// check for various command-line argument problems
if (verify_only && delete_source) {
error_line ("can't delete in verify mode!");
delete_source = 0;
}
if (verify_only && outfilename) {
error_line ("outfile specification and verify mode are incompatible!");
usage_error = 1;
}
if (!quiet_mode && !usage_error)
fprintf (stderr, sign_on, VERSION_OS, VERSION_STR, DATE_STR);
if (!infilename) {
printf ("%s", usage);
return 0;
}
if (usage_error) {
free (infilename);
return 0;
}
setup_break ();
// If the infile specification begins with a '@', then it actually points
// to a file that contains the names of the files to be converted. This
// was included for use by Wim Speekenbrink's frontends, but could be used
// for other purposes.
if (infilename [0] == '@') {
FILE *list = fopen (infilename+1, "rt");
int c;
if (list == NULL) {
error_line ("file %s not found!", infilename+1);
free(infilename);
return 1;
}
while ((c = getc (list)) != EOF) {
while (c == '\n')
c = getc (list);
if (c != EOF) {
char *fname = malloc (PATH_MAX);
int ci = 0;
do
fname [ci++] = c;
while ((c = getc (list)) != '\n' && c != EOF && ci < PATH_MAX);
fname [ci++] = '\0';
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = realloc (fname, ci);
}
}
fclose (list);
free (infilename);
infilename = NULL;
filelist = 1;
}
else if (*infilename != '-') { // skip this if infile is stdin (-)
if (!filespec_ext (infilename))
strcat (infilename, ".wv");
#ifdef NO_WILDCARDS
matches = malloc (sizeof (*matches));
matches [num_files++] = infilename;
filelist = 1;
#else
// search for and store any filenames that match the user supplied spec
#ifdef __BORLANDC__
if (findfirst (infilename, &ffblk, 0) == 0) {
do {
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (ffblk.ff_name);
} while (findnext (&ffblk) == 0);
}
#elif defined (WIN32)
if ((i = _findfirst (infilename, &_finddata_t)) != -1L) {
do {
if (!(_finddata_t.attrib & _A_SUBDIR)) {
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (_finddata_t.name);
}
} while (_findnext (i, &_finddata_t) == 0);
_findclose (i);
}
#else
i = 0;
if (glob(infilename, 0, NULL, &globs) == 0 && globs.gl_pathc > 0) {
do {
if (stat(globs.gl_pathv[i], &fstats) == 0 && !(fstats.st_mode & S_IFDIR)) {
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (globs.gl_pathv[i]);
}
} while (i++ < globs.gl_pathc);
}
globfree(&globs);
#endif
#endif
}
else { // handle case of stdin (-)
matches = malloc (sizeof (*matches));
matches [num_files++] = infilename;
}
// If the outfile specification begins with a '@', then it actually points
// to a file that contains the output specification. This was included for
// use by Wim Speekenbrink's frontends because certain filenames could not
// be passed on the command-line, but could be used for other purposes.
if (outfilename && outfilename [0] == '@') {
FILE *list = fopen (outfilename+1, "rt");
int c;
if (list == NULL) {
error_line ("file %s not found!", outfilename+1);
free(outfilename);
return 1;
}
while ((c = getc (list)) == '\n');
if (c != EOF) {
int ci = 0;
do
outfilename [ci++] = c;
while ((c = getc (list)) != '\n' && c != EOF && ci < PATH_MAX);
outfilename [ci] = '\0';
}
else {
error_line ("output spec file is empty!");
free(outfilename);
fclose (list);
return 1;
}
fclose (list);
}
// if we found any files to process, this is where we start
if (num_files) {
int soft_errors = 0;
if (outfilename && *outfilename != '-') {
outpath = (filespec_path (outfilename) != NULL);
if (num_files > 1 && !outpath) {
error_line ("%s is not a valid output path", outfilename);
free(outfilename);
return 1;
}
}
else
outpath = 0;
add_extension = !outfilename || outpath || !filespec_ext (outfilename);
// loop through and process files in list
for (file_index = 0; file_index < num_files; ++file_index) {
if (check_break ())
break;
// get input filename from list
if (filelist)
infilename = matches [file_index];
else if (*infilename != '-') {
*filespec_name (infilename) = '\0';
strcat (infilename, matches [file_index]);
}
// generate output filename
if (outpath) {
strcat (outfilename, filespec_name (matches [file_index]));
if (filespec_ext (outfilename))
*filespec_ext (outfilename) = '\0';
}
else if (!outfilename) {
outfilename = malloc (strlen (infilename) + 10);
strcpy (outfilename, infilename);
if (filespec_ext (outfilename))
*filespec_ext (outfilename) = '\0';
}
if (outfilename && *outfilename != '-' && add_extension)
strcat (outfilename, raw_decode ? ".raw" : ".wav");
if (num_files > 1)
fprintf (stderr, "\n%s:\n", infilename);
result = unpack_file (infilename, verify_only ? NULL : outfilename);
if (result == HARD_ERROR)
break;
else if (result == SOFT_ERROR)
++soft_errors;
// clean up in preparation for potentially another file
if (outpath)
*filespec_name (outfilename) = '\0';
else if (*outfilename != '-') {
free (outfilename);
outfilename = NULL;
}
free (matches [file_index]);
}
if (num_files > 1) {
if (soft_errors)
fprintf (stderr, "\n **** warning: errors occurred in %d of %d files! ****\n", soft_errors, num_files);
else if (!quiet_mode)
fprintf (stderr, "\n **** %d files successfully processed ****\n", num_files);
}
free (matches);
}
else
error_line (filespec_wild (infilename) ? "nothing to do!" :
"file %s not found!", infilename);
if (outfilename)
free(outfilename);
#ifdef DEBUG_ALLOC
error_line ("malloc_count = %d", dump_alloc ());
#endif
return 0;
}
// Unpack the specified WavPack input file into the specified output file name.
// This function uses the library routines provided in wputils.c to do all
// unpacking. This function takes care of reformatting the data (which is
// returned in native-endian longs) to the standard little-endian format. This
// function also handles optionally calculating and displaying the MD5 sum of
// the resulting audio data and verifying the sum if a sum was stored in the
// source and lossless compression is used.
static uchar *format_samples (int bps, uchar *dst, int32_t *src, uint32_t samcnt);
static void dump_summary (WavpackContext *wpc, char *name, FILE *dst);
extern int delta_blocks [8];
static int unpack_file (char *infilename, char *outfilename)
{
int result = NO_ERROR, md5_diff = FALSE, open_flags = 0, bytes_per_sample, num_channels, wvc_mode, bps;
uint32_t outfile_length, output_buffer_size, bcount, total_unpacked_samples = 0;
uchar *output_buffer = NULL, *output_pointer = NULL;
double dtime, progress = -1.0;
MD5_CTX md5_context;
WavpackContext *wpc;
int32_t *temp_buffer;
char error [80];
FILE *outfile;
#ifdef __BORLANDC__
struct time time1, time2;
#elif defined(WIN32)
struct _timeb time1, time2;
#else
struct timeval time1, time2;
struct timezone timez;
#endif
// use library to open WavPack file
if (outfilename && !raw_decode)
open_flags |= OPEN_WRAPPER;
if (raw_decode)
open_flags |= OPEN_STREAMING;
if (!ignore_wvc)
open_flags |= OPEN_WVC;
wpc = WavpackOpenFileInput (infilename, error, open_flags, 0);
if (!wpc) {
error_line (error);
return SOFT_ERROR;
}
if (calc_md5)
MD5Init (&md5_context);
wvc_mode = WavpackGetMode (wpc) & MODE_WVC;
num_channels = WavpackGetNumChannels (wpc);
bps = WavpackGetBytesPerSample (wpc);
bytes_per_sample = num_channels * bps;
if (summary) {
dump_summary (wpc, infilename, stdout);
WavpackCloseFile (wpc);
return NO_ERROR;
}
if (outfilename) {
if (*outfilename != '-') {
// check the output file for overwrite warning required
if (!overwrite_all && (outfile = fopen (outfilename, "rb")) != NULL) {
DoCloseHandle (outfile);
fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (outfilename));
SetConsoleTitle ("overwrite?");
switch (yna ()) {
case 'n':
result = SOFT_ERROR;
break;
case 'a':
overwrite_all = 1;
}
if (result != NO_ERROR) {
WavpackCloseFile (wpc);
return result;
}
}
// open output file for writing
if ((outfile = fopen (outfilename, "wb")) == NULL) {
error_line ("can't create file %s!", outfilename);
WavpackCloseFile (wpc);
return SOFT_ERROR;
}
else if (!quiet_mode)
fprintf (stderr, "restoring %s,", FN_FIT (outfilename));
}
else { // come here to open stdout as destination
outfile = stdout;
#if defined(WIN32)
setmode (fileno (stdout), O_BINARY);
#endif
if (!quiet_mode)
fprintf (stderr, "unpacking %s%s to stdout,", *infilename == '-' ?
"stdin" : FN_FIT (infilename), wvc_mode ? " (+.wvc)" : "");
}
if (outbuf_k)
output_buffer_size = outbuf_k * 1024;
else
output_buffer_size = 1024 * 256;
output_pointer = output_buffer = malloc (output_buffer_size);
}
else { // in verify only mode we don't worry about headers
outfile = NULL;
if (!quiet_mode)
fprintf (stderr, "verifying %s%s,", *infilename == '-' ? "stdin" :
FN_FIT (infilename), wvc_mode ? " (+.wvc)" : "");
}
#ifdef __BORLANDC__
gettime (&time1);
#elif defined(WIN32)
_ftime (&time1);
#else
gettimeofday(&time1,&timez);
#endif
if (WavpackGetWrapperBytes (wpc)) {
if (outfile && (!DoWriteFile (outfile, WavpackGetWrapperData (wpc), WavpackGetWrapperBytes (wpc), &bcount) ||
bcount != WavpackGetWrapperBytes (wpc))) {
error_line ("can't write .WAV data, disk probably full!");
DoTruncateFile (outfile);
result = HARD_ERROR;
}
WavpackFreeWrapper (wpc);
}
temp_buffer = malloc (4096L * num_channels * 4);
while (result == NO_ERROR) {
uint32_t samples_to_unpack, samples_unpacked;
if (output_buffer) {
samples_to_unpack = (output_buffer_size - (output_pointer - output_buffer)) / bytes_per_sample;
if (samples_to_unpack > 4096)
samples_to_unpack = 4096;
}
else
samples_to_unpack = 4096;
samples_unpacked = WavpackUnpackSamples (wpc, temp_buffer, samples_to_unpack);
total_unpacked_samples += samples_unpacked;
if (output_buffer) {
if (samples_unpacked)
output_pointer = format_samples (bps, output_pointer, temp_buffer, samples_unpacked * num_channels);
if (!samples_unpacked || (output_buffer_size - (output_pointer - output_buffer)) < bytes_per_sample) {
if (!DoWriteFile (outfile, output_buffer, output_pointer - output_buffer, &bcount) ||
bcount != output_pointer - output_buffer) {
error_line ("can't write .WAV data, disk probably full!");
DoTruncateFile (outfile);
result = HARD_ERROR;
break;
}
output_pointer = output_buffer;
}
}
if (calc_md5 && samples_unpacked) {
format_samples (bps, (uchar *) temp_buffer, temp_buffer, samples_unpacked * num_channels);
MD5Update (&md5_context, temp_buffer, bps * samples_unpacked * num_channels);
}
if (!samples_unpacked)
break;
if (check_break ()) {
fprintf (stderr, "^C\n");
DoTruncateFile (outfile);
result = SOFT_ERROR;
break;
}
if (WavpackGetProgress (wpc) != -1.0 &&
progress != floor (WavpackGetProgress (wpc) * 100.0 + 0.5)) {
int nobs = progress == -1.0;
progress = WavpackGetProgress (wpc);
display_progress (progress);
progress = floor (progress * 100.0 + 0.5);
if (!quiet_mode)
fprintf (stderr, "%s%3d%% done...",
nobs ? " " : "\b\b\b\b\b\b\b\b\b\b\b\b", (int) progress);
}
}
free (temp_buffer);
if (output_buffer)
free (output_buffer);
if (0) {
int i;
for (i = 0; i < 8; ++i)
error_line ("delta = %d, count = %d", i, delta_blocks [i]);
}
if (!check_break () && calc_md5) {
char md5_string1 [] = "00000000000000000000000000000000";
char md5_string2 [] = "00000000000000000000000000000000";
uchar md5_original [16], md5_unpacked [16];
int i;
MD5Final (md5_unpacked, &md5_context);
if (WavpackGetMD5Sum (wpc, md5_original)) {
for (i = 0; i < 16; ++i)
sprintf (md5_string1 + (i * 2), "%02x", md5_original [i]);
error_line ("original md5: %s", md5_string1);
if (memcmp (md5_unpacked, md5_original, 16))
md5_diff = TRUE;
}
for (i = 0; i < 16; ++i)
sprintf (md5_string2 + (i * 2), "%02x", md5_unpacked [i]);
error_line ("unpacked md5: %s", md5_string2);
}
if (WavpackGetWrapperBytes (wpc)) {
if (outfile && result == NO_ERROR &&
(!DoWriteFile (outfile, WavpackGetWrapperData (wpc), WavpackGetWrapperBytes (wpc), &bcount) ||
bcount != WavpackGetWrapperBytes (wpc))) {
error_line ("can't write .WAV data, disk probably full!");
DoTruncateFile (outfile);
result = HARD_ERROR;
}
WavpackFreeWrapper (wpc);
}
// if we are not just in verify only mode, grab the size of the output
// file and close the file
if (outfile != NULL) {
fflush (outfile);
outfile_length = DoGetFileSize (outfile);
if (!DoCloseHandle (outfile)) {
error_line ("can't close file!");
result = SOFT_ERROR;
}
if (outfilename && *outfilename != '-' && !outfile_length)
DoDeleteFile (outfilename);
}
#if defined (WIN32)
if (result == NO_ERROR && copy_time && outfilename &&
!copy_timestamp (infilename, outfilename))
error_line ("failure copying time stamp!");
#endif
if (result == NO_ERROR && WavpackGetNumSamples (wpc) != (uint32_t) -1 &&
total_unpacked_samples != WavpackGetNumSamples (wpc)) {
error_line ("incorrect number of samples!");
result = SOFT_ERROR;
}
if (result == NO_ERROR && WavpackGetNumErrors (wpc)) {
error_line ("crc errors detected in %d block(s)!", WavpackGetNumErrors (wpc));
result = SOFT_ERROR;
}
else if (result == NO_ERROR && md5_diff && (WavpackGetMode (wpc) & MODE_LOSSLESS)) {
error_line ("MD5 signatures should match, but do not!");
result = SOFT_ERROR;
}
// Compute and display the time consumed along with some other details of
// the unpacking operation (assuming there was no error).
#ifdef __BORLANDC__
gettime (&time2);
dtime = time2.ti_sec * 100.0 + time2.ti_hund + time2.ti_min * 6000.0 + time2.ti_hour * 360000.00;
dtime -= time1.ti_sec * 100.0 + time1.ti_hund + time1.ti_min * 6000.0 + time1.ti_hour * 360000.00;
if ((dtime /= 100.0) < 0.0)
dtime += 86400.0;
#elif defined(WIN32)
_ftime (&time2);
dtime = time2.time + time2.millitm / 1000.0;
dtime -= time1.time + time1.millitm / 1000.0;
#else
gettimeofday(&time2,&timez);
dtime = time2.tv_sec + time2.tv_usec / 1000000.0;
dtime -= time1.tv_sec + time1.tv_usec / 1000000.0;
#endif
if (result == NO_ERROR && !quiet_mode) {
char *file, *fext, *oper, *cmode, cratio [16] = "";
if (outfilename && *outfilename != '-') {
file = FN_FIT (outfilename);
fext = "";
oper = "restored";
}
else {
file = (*infilename == '-') ? "stdin" : FN_FIT (infilename);
fext = wvc_mode ? " (+.wvc)" : "";
oper = outfilename ? "unpacked" : "verified";
}
if (WavpackGetMode (wpc) & MODE_LOSSLESS) {
cmode = "lossless";
if (WavpackGetRatio (wpc) != 0.0)
sprintf (cratio, ", %.2f%%", 100.0 - WavpackGetRatio (wpc) * 100.0);
}
else {
cmode = "lossy";
if (WavpackGetAverageBitrate (wpc, TRUE) != 0.0)
sprintf (cratio, ", %d kbps", (int) (WavpackGetAverageBitrate (wpc, TRUE) / 1000.0));
}
error_line ("%s %s%s in %.2f secs (%s%s)", oper, file, fext, dtime, cmode, cratio);
}
WavpackCloseFile (wpc);
if (result == NO_ERROR && delete_source) {
error_line ("%s source file %s", DoDeleteFile (infilename) ?
"deleted" : "can't delete", infilename);
if (wvc_mode) {
char in2filename [PATH_MAX];
strcpy (in2filename, infilename);
strcat (in2filename, "c");
error_line ("%s source file %s", DoDeleteFile (in2filename) ?
"deleted" : "can't delete", in2filename);
}
}
return result;
}
// Reformat samples from longs in processor's native endian mode to
// little-endian data with (possibly) less than 4 bytes / sample.
static uchar *format_samples (int bps, uchar *dst, int32_t *src, uint32_t samcnt)
{
int32_t temp;
switch (bps) {
case 1:
while (samcnt--)
*dst++ = *src++ + 128;
break;
case 2:
while (samcnt--) {
*dst++ = (uchar) (temp = *src++);
*dst++ = (uchar) (temp >> 8);
}
break;
case 3:
while (samcnt--) {
*dst++ = (uchar) (temp = *src++);
*dst++ = (uchar) (temp >> 8);
*dst++ = (uchar) (temp >> 16);
}
break;
case 4:
while (samcnt--) {
*dst++ = (uchar) (temp = *src++);
*dst++ = (uchar) (temp >> 8);
*dst++ = (uchar) (temp >> 16);
*dst++ = (uchar) (temp >> 24);
}
break;
}
return dst;
}
static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
{
int num_channels = WavpackGetNumChannels (wpc);
uchar md5_sum [16], modes [80];
fprintf (dst, "\n");
if (name && *name != '-') {
fprintf (dst, "file name: %s%s\n", name, (WavpackGetMode (wpc) & MODE_WVC) ? " (+wvc)" : "");
fprintf (dst, "file size: %lu bytes\n", WavpackGetFileSize (wpc));
}
fprintf (dst, "source: %d-bit %s at %ld Hz\n", WavpackGetBitsPerSample (wpc),
(WavpackGetMode (wpc) & MODE_FLOAT) ? "floats" : "ints",
WavpackGetSampleRate (wpc));
fprintf (dst, "channels: %d (%s)\n", num_channels,
num_channels > 2 ? "multichannel" : (num_channels == 1 ? "mono" : "stereo"));
if (WavpackGetNumSamples (wpc) != (uint32_t) -1) {
double seconds = (double) WavpackGetNumSamples (wpc) / WavpackGetSampleRate (wpc);
int minutes = (int) floor (seconds / 60.0);
int hours = (int) floor (seconds / 3600.0);
seconds -= minutes * 60.0;
minutes -= hours * 60.0;
fprintf (dst, "duration: %d:%02d:%0.2f\n", hours, minutes, seconds);
}
modes [0] = 0;
if (WavpackGetMode (wpc) & MODE_HYBRID)
strcat (modes, "hybrid ");
strcat (modes, (WavpackGetMode (wpc) & MODE_LOSSLESS) ? "lossless" : "lossy");
if (WavpackGetMode (wpc) & MODE_FAST)
strcat (modes, ", fast");
else if (WavpackGetMode (wpc) & MODE_HIGH)
strcat (modes, ", high");
if (WavpackGetMode (wpc) & MODE_EXTRA)
strcat (modes, ", extra");
if (WavpackGetMode (wpc) & MODE_SFX)
strcat (modes, ", sfx");
fprintf (dst, "modalities: %s\n", modes);
if (WavpackGetRatio (wpc) != 0.0) {
fprintf (dst, "compression: %.2f%%\n", 100.0 - (100 * WavpackGetRatio (wpc)));
fprintf (dst, "ave bitrate: %d kbps\n", (int) ((WavpackGetAverageBitrate (wpc, TRUE) + 500.0) / 1000.0));
if (WavpackGetMode (wpc) & MODE_WVC)
fprintf (dst, "ave lossy bitrate: %d kbps\n", (int) ((WavpackGetAverageBitrate (wpc, FALSE) + 500.0) / 1000.0));
}
if (WavpackGetVersion (wpc))
fprintf (dst, "encoder version: %d\n", WavpackGetVersion (wpc));
if (WavpackGetMD5Sum (wpc, md5_sum)) {
char md5_string [] = "00000000000000000000000000000000";
int i;
for (i = 0; i < 16; ++i)
sprintf (md5_string + (i * 2), "%02x", md5_sum [i]);
fprintf (dst, "original md5: %s\n", md5_string);
}
}
//////////////////////////////////////////////////////////////////////////////
// This function displays the progress status on the title bar of the DOS //
// window that WavPack is running in. The "file_progress" argument is for //
// the current file only and ranges from 0 - 1; this function takes into //
// account the total number of files to generate a batch progress number. //
//////////////////////////////////////////////////////////////////////////////
void display_progress (double file_progress)
{
char title [40];
file_progress = (file_index + file_progress) / num_files;
sprintf (title, "%d%% (WvUnpack)", (int) ((file_progress * 100.0) + 0.5));
SetConsoleTitle (title);
}