Added new SHN decoder (Derek Scott)
parent
38ff1f798c
commit
4a4672a6b9
|
@ -14,6 +14,7 @@
|
|||
8E1296DA0A2BA9CE00443124 /* PlaylistHeaderView.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E1296D80A2BA9CE00443124 /* PlaylistHeaderView.h */; };
|
||||
8E1296DB0A2BA9CE00443124 /* PlaylistHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E1296D90A2BA9CE00443124 /* PlaylistHeaderView.m */; };
|
||||
8E4C7F090A0509FC003BE25F /* DragScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E4C7F070A0509FC003BE25F /* DragScrollView.m */; };
|
||||
8E4CAB5B0A32251B00214C1D /* ShnFile.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8E4CAB5A0A32251B00214C1D /* ShnFile.mm */; };
|
||||
8E6A8E2C0A0D8A68002ABE9C /* CoreAudioFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6A8E280A0D8A68002ABE9C /* CoreAudioFile.m */; };
|
||||
8E6A8E380A0D8AD8002ABE9C /* CoreAudioUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6A8E360A0D8AD8002ABE9C /* CoreAudioUtils.m */; };
|
||||
8E75756909F31D5A0080F1EE /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E75751909F31D5A0080F1EE /* AppController.m */; };
|
||||
|
@ -39,7 +40,6 @@
|
|||
8E75757E09F31D5A0080F1EE /* FlacFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E75754809F31D5A0080F1EE /* FlacFile.m */; };
|
||||
8E75757F09F31D5A0080F1EE /* MonkeysFile.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8E75754A09F31D5A0080F1EE /* MonkeysFile.mm */; };
|
||||
8E75758109F31D5A0080F1EE /* MusepackFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E75754E09F31D5A0080F1EE /* MusepackFile.m */; };
|
||||
8E75758209F31D5A0080F1EE /* ShnFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E75755009F31D5A0080F1EE /* ShnFile.m */; };
|
||||
8E75758309F31D5A0080F1EE /* SoundFile.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8E75755209F31D5A0080F1EE /* SoundFile.mm */; };
|
||||
8E75758409F31D5A0080F1EE /* VorbisFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E75755409F31D5A0080F1EE /* VorbisFile.m */; };
|
||||
8E75758609F31D5A0080F1EE /* WavPackFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E75755809F31D5A0080F1EE /* WavPackFile.m */; };
|
||||
|
@ -84,14 +84,12 @@
|
|||
8E75774009F31F2A0080F1EE /* MAC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75773F09F31F2A0080F1EE /* MAC.framework */; };
|
||||
8E75774409F31F370080F1EE /* MPCDec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75774309F31F370080F1EE /* MPCDec.framework */; };
|
||||
8E75774709F31F450080F1EE /* Ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75774609F31F450080F1EE /* Ogg.framework */; };
|
||||
8E75774B09F31F500080F1EE /* Shorten.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75774A09F31F500080F1EE /* Shorten.framework */; };
|
||||
8E75774E09F31F600080F1EE /* TagLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75774D09F31F600080F1EE /* TagLib.framework */; };
|
||||
8E75775109F31F6B0080F1EE /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75775009F31F6B0080F1EE /* Vorbis.framework */; };
|
||||
8E75775409F31F750080F1EE /* WavPack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E75775309F31F750080F1EE /* WavPack.framework */; };
|
||||
8E757B4F09F326710080F1EE /* WavPack.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75775309F31F750080F1EE /* WavPack.framework */; };
|
||||
8E757B5009F326710080F1EE /* Vorbis.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75775009F31F6B0080F1EE /* Vorbis.framework */; };
|
||||
8E757B5109F326710080F1EE /* TagLib.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75774D09F31F600080F1EE /* TagLib.framework */; };
|
||||
8E757B5209F326710080F1EE /* Shorten.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75774A09F31F500080F1EE /* Shorten.framework */; };
|
||||
8E757B5309F326710080F1EE /* Ogg.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75774609F31F450080F1EE /* Ogg.framework */; };
|
||||
8E757B5409F326710080F1EE /* MPCDec.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75774309F31F370080F1EE /* MPCDec.framework */; };
|
||||
8E757B5509F326710080F1EE /* MAC.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E75773F09F31F2A0080F1EE /* MAC.framework */; };
|
||||
|
@ -127,7 +125,6 @@
|
|||
8E757B4F09F326710080F1EE /* WavPack.framework in CopyFiles */,
|
||||
8E757B5009F326710080F1EE /* Vorbis.framework in CopyFiles */,
|
||||
8E757B5109F326710080F1EE /* TagLib.framework in CopyFiles */,
|
||||
8E757B5209F326710080F1EE /* Shorten.framework in CopyFiles */,
|
||||
8E757B5309F326710080F1EE /* Ogg.framework in CopyFiles */,
|
||||
8E757B5409F326710080F1EE /* MPCDec.framework in CopyFiles */,
|
||||
8E757B5509F326710080F1EE /* MAC.framework in CopyFiles */,
|
||||
|
@ -163,6 +160,7 @@
|
|||
8E1296D90A2BA9CE00443124 /* PlaylistHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PlaylistHeaderView.m; sourceTree = "<group>"; };
|
||||
8E4C7F060A0509FC003BE25F /* DragScrollView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DragScrollView.h; sourceTree = "<group>"; };
|
||||
8E4C7F070A0509FC003BE25F /* DragScrollView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DragScrollView.m; sourceTree = "<group>"; };
|
||||
8E4CAB5A0A32251B00214C1D /* ShnFile.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = ShnFile.mm; sourceTree = "<group>"; };
|
||||
8E643DF20A2B585600844A28 /* GameFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameFile.h; sourceTree = "<group>"; };
|
||||
8E643DF30A2B585600844A28 /* GameFile.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GameFile.mm; sourceTree = "<group>"; };
|
||||
8E6A8E270A0D8A68002ABE9C /* CoreAudioFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CoreAudioFile.h; sourceTree = "<group>"; };
|
||||
|
@ -221,7 +219,6 @@
|
|||
8E75754D09F31D5A0080F1EE /* MusepackFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MusepackFile.h; sourceTree = "<group>"; };
|
||||
8E75754E09F31D5A0080F1EE /* MusepackFile.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MusepackFile.m; sourceTree = "<group>"; };
|
||||
8E75754F09F31D5A0080F1EE /* ShnFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ShnFile.h; sourceTree = "<group>"; };
|
||||
8E75755009F31D5A0080F1EE /* ShnFile.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ShnFile.m; sourceTree = "<group>"; };
|
||||
8E75755109F31D5A0080F1EE /* SoundFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SoundFile.h; sourceTree = "<group>"; };
|
||||
8E75755209F31D5A0080F1EE /* SoundFile.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = SoundFile.mm; sourceTree = "<group>"; };
|
||||
8E75755309F31D5A0080F1EE /* VorbisFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VorbisFile.h; sourceTree = "<group>"; };
|
||||
|
@ -280,7 +277,6 @@
|
|||
8E75773F09F31F2A0080F1EE /* MAC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MAC.framework; path = Libraries/MAC/build/Release/MAC.framework; sourceTree = "<group>"; };
|
||||
8E75774309F31F370080F1EE /* MPCDec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MPCDec.framework; path = Libraries/MPCDec/build/Release/MPCDec.framework; sourceTree = "<group>"; };
|
||||
8E75774609F31F450080F1EE /* Ogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Ogg.framework; path = Libraries/Ogg/build/Release/Ogg.framework; sourceTree = "<group>"; };
|
||||
8E75774A09F31F500080F1EE /* Shorten.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Shorten.framework; path = Libraries/Shorten/build/Release/Shorten.framework; sourceTree = "<group>"; };
|
||||
8E75774D09F31F600080F1EE /* TagLib.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TagLib.framework; path = Libraries/TagLib/build/Release/TagLib.framework; sourceTree = "<group>"; };
|
||||
8E75775009F31F6B0080F1EE /* Vorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vorbis.framework; path = Libraries/Vorbis/build/Release/Vorbis.framework; sourceTree = "<group>"; };
|
||||
8E75775309F31F750080F1EE /* WavPack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WavPack.framework; path = Libraries/WavPack/build/Release/WavPack.framework; sourceTree = "<group>"; };
|
||||
|
@ -301,7 +297,6 @@
|
|||
8E75774009F31F2A0080F1EE /* MAC.framework in Frameworks */,
|
||||
8E75774409F31F370080F1EE /* MPCDec.framework in Frameworks */,
|
||||
8E75774709F31F450080F1EE /* Ogg.framework in Frameworks */,
|
||||
8E75774B09F31F500080F1EE /* Shorten.framework in Frameworks */,
|
||||
8E75774E09F31F600080F1EE /* TagLib.framework in Frameworks */,
|
||||
8E75775109F31F6B0080F1EE /* Vorbis.framework in Frameworks */,
|
||||
8E75775409F31F750080F1EE /* WavPack.framework in Frameworks */,
|
||||
|
@ -497,7 +492,7 @@
|
|||
8E75754D09F31D5A0080F1EE /* MusepackFile.h */,
|
||||
8E75754E09F31D5A0080F1EE /* MusepackFile.m */,
|
||||
8E75754F09F31D5A0080F1EE /* ShnFile.h */,
|
||||
8E75755009F31D5A0080F1EE /* ShnFile.m */,
|
||||
8E4CAB5A0A32251B00214C1D /* ShnFile.mm */,
|
||||
8E75755109F31D5A0080F1EE /* SoundFile.h */,
|
||||
8E75755209F31D5A0080F1EE /* SoundFile.mm */,
|
||||
8E75755309F31D5A0080F1EE /* VorbisFile.h */,
|
||||
|
@ -573,7 +568,6 @@
|
|||
8E75775309F31F750080F1EE /* WavPack.framework */,
|
||||
8E75775009F31F6B0080F1EE /* Vorbis.framework */,
|
||||
8E75774D09F31F600080F1EE /* TagLib.framework */,
|
||||
8E75774A09F31F500080F1EE /* Shorten.framework */,
|
||||
8E75774609F31F450080F1EE /* Ogg.framework */,
|
||||
8E75774309F31F370080F1EE /* MPCDec.framework */,
|
||||
8E75773F09F31F2A0080F1EE /* MAC.framework */,
|
||||
|
@ -704,7 +698,6 @@
|
|||
8E75757E09F31D5A0080F1EE /* FlacFile.m in Sources */,
|
||||
8E75757F09F31D5A0080F1EE /* MonkeysFile.mm in Sources */,
|
||||
8E75758109F31D5A0080F1EE /* MusepackFile.m in Sources */,
|
||||
8E75758209F31D5A0080F1EE /* ShnFile.m in Sources */,
|
||||
8E75758309F31D5A0080F1EE /* SoundFile.mm in Sources */,
|
||||
8E75758409F31D5A0080F1EE /* VorbisFile.m in Sources */,
|
||||
8E75758609F31D5A0080F1EE /* WavPackFile.m in Sources */,
|
||||
|
@ -717,6 +710,7 @@
|
|||
8E6A8E2C0A0D8A68002ABE9C /* CoreAudioFile.m in Sources */,
|
||||
8E6A8E380A0D8AD8002ABE9C /* CoreAudioUtils.m in Sources */,
|
||||
8E1296DB0A2BA9CE00443124 /* PlaylistHeaderView.m in Sources */,
|
||||
8E4CAB5B0A32251B00214C1D /* ShnFile.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Millennium Sound System
|
||||
©1999, Subband Software
|
||||
|
||||
Description: GP Ring Buffer
|
||||
Released: 9/15/99
|
||||
|
||||
Version history:
|
||||
|
||||
Date Who Changes
|
||||
--------+---------+------------------------------------------------------
|
||||
09-15-99 DAB Initial release.
|
||||
|
||||
DAB = Dmitry Boldyrev
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __RINGBUFFER_H__
|
||||
#define __RINGBUFFER_H__
|
||||
|
||||
class RingBuffer
|
||||
{
|
||||
public:
|
||||
RingBuffer();
|
||||
~RingBuffer();
|
||||
|
||||
int Init(long inSize);
|
||||
|
||||
long WriteData(char *data, long len);
|
||||
long ReadData(char *data, long len);
|
||||
|
||||
long FreeSpace(bool inTrueSpace = true);
|
||||
long UsedSpace(bool inTrueSpace = true);
|
||||
long BufSize()
|
||||
{
|
||||
return mBufSize;
|
||||
}
|
||||
|
||||
void Empty();
|
||||
|
||||
void SaveRead();
|
||||
void RestoreRead();
|
||||
|
||||
bool IsReadMode()
|
||||
{
|
||||
return mSaveFreeSpace == -1;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
char* mBuffer;
|
||||
long mBufSize;
|
||||
long mBufWxIdx;
|
||||
|
||||
long mBufRdIdx;
|
||||
long mFreeSpace;
|
||||
|
||||
long mSaveFreeSpace;
|
||||
long mSaveReadPos;
|
||||
};
|
||||
|
||||
#endif //__RINGBUFFER_H__
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* shn_reader.h
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Sun Jul 07 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/* xmms-shn - a shorten (.shn) plugin for XMMS
|
||||
* Copyright (C) 2000-2001 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: shn.h,v 1.6 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SHN_READER_H__
|
||||
#define __SHN_READER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include "shorten.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
|
||||
/* Derek */
|
||||
typedef unsigned int uint;
|
||||
|
||||
/* surely no headers will be this large. right? RIGHT? */
|
||||
#define OUT_BUFFER_SIZE 16384
|
||||
#define NUM_DEFAULT_BUFFER_BLOCKS 512L
|
||||
|
||||
#define SEEK_HEADER_SIZE 12
|
||||
#define SEEK_TRAILER_SIZE 12
|
||||
#define SEEK_ENTRY_SIZE 80
|
||||
|
||||
#define MASKTABSIZE 33
|
||||
|
||||
typedef struct _shn_decode_state
|
||||
{
|
||||
uchar *getbuf;
|
||||
uchar *getbufp;
|
||||
int nbitget;
|
||||
int nbyteget;
|
||||
ulong gbuffer;
|
||||
char *writebuf;
|
||||
char *writefub;
|
||||
int nwritebuf;
|
||||
} shn_decode_state;
|
||||
|
||||
typedef struct _shn_seek_header
|
||||
{
|
||||
uchar data[SEEK_HEADER_SIZE];
|
||||
ulong 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;
|
||||
|
||||
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;
|
||||
ulong problems;
|
||||
} shn_wave_header;
|
||||
|
||||
class shn_reader
|
||||
{
|
||||
private:
|
||||
shn_decode_state mDecodeState;
|
||||
shn_wave_header mWAVEHeader;
|
||||
shn_seek_header mSeekHeader;
|
||||
shn_seek_trailer mSeekTrailer;
|
||||
shn_seek_entry *mSeekTable;
|
||||
int mSeekTo;
|
||||
bool mEOF;
|
||||
bool mGoing;
|
||||
long mSeekTableEntries;
|
||||
int mBytesInBuf;
|
||||
uchar mBuffer[OUT_BUFFER_SIZE];
|
||||
int mBytesInHeader;
|
||||
uchar mHeader[OUT_BUFFER_SIZE];
|
||||
bool mFatalError;
|
||||
FILE *mFP;
|
||||
RingBuffer mRing;
|
||||
pthread_mutex_t mRingLock;
|
||||
pthread_cond_t mRunCond;
|
||||
pthread_t mThread;
|
||||
|
||||
ulong masktab[MASKTABSIZE];
|
||||
int sizeof_sample[TYPE_EOF];
|
||||
|
||||
public:
|
||||
shn_reader();
|
||||
~shn_reader();
|
||||
int open(const char *fn, bool should_load_seek_table = true);
|
||||
int go();
|
||||
void exit();
|
||||
bool file_info(long *size, int *nch, float *rate, float *time,
|
||||
int *samplebits, bool *seekable);
|
||||
long read(void *buf, long size);
|
||||
float seek(float sec);
|
||||
int shn_get_buffer_block_size(int blocks);//derek
|
||||
unsigned int shn_get_song_length();//derek
|
||||
|
||||
private:
|
||||
void init();
|
||||
void Run();
|
||||
|
||||
int get_wave_header();
|
||||
int verify_header();
|
||||
void init_decode_state();
|
||||
void write_and_wait(int block_size);
|
||||
|
||||
/* fixio.cpp */
|
||||
void init_sizeof_sample();
|
||||
void fwrite_type_init();
|
||||
void fwrite_type_quit();
|
||||
void fix_bitshift(slong *buffer, int nitem, int bitshift, int ftype);
|
||||
void fwrite_type(slong **data,int ftype,int nchan,int nitem);
|
||||
|
||||
/* vario.cpp */
|
||||
void var_get_init();
|
||||
ulong word_get();
|
||||
long uvar_get(int nbin);
|
||||
ulong ulong_get();
|
||||
long var_get(int nbin);
|
||||
void var_get_quit();
|
||||
|
||||
/* seek.cpp */
|
||||
void load_seek_table(const char *fn);
|
||||
int load_separate_seek_table(const char *fn);
|
||||
shn_seek_entry *seek_entry_search(ulong goal, ulong min, ulong max);
|
||||
|
||||
/* array.cpp */
|
||||
void *pmalloc(ulong size);
|
||||
slong **long2d(ulong n0, ulong n1);
|
||||
|
||||
friend void *thread_runner(shn_reader *reader)
|
||||
{
|
||||
reader->Run();
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
inline ulong 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]);
|
||||
}
|
||||
|
||||
inline slong uchar_to_slong_le(uchar *buf)
|
||||
/* converts 4 bytes stored in little-endian format to an slong */
|
||||
{
|
||||
return (long)uchar_to_ulong_le(buf);
|
||||
}
|
||||
|
||||
inline ushort uchar_to_ushort_le(uchar *buf)
|
||||
/* converts 4 bytes stored in little-endian format to a ushort */
|
||||
{
|
||||
return (ushort)((buf[1] << 8) + buf[0]);
|
||||
}
|
||||
|
||||
#endif /*__SHN_READER_H__*/
|
|
@ -1,3 +1,12 @@
|
|||
/*
|
||||
* shorten.h
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Sun Jul 07 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 1992-1995 Tony Robinson *
|
||||
|
@ -7,7 +16,7 @@
|
|||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: shorten.h 19 2005-06-07 04:16:15Z vspader $
|
||||
* $Id: shorten.h,v 1.4 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SHORTEN_H
|
||||
|
@ -18,7 +27,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
|
@ -49,8 +57,6 @@
|
|||
#define sshort int16_t
|
||||
#define schar int8_t
|
||||
|
||||
#include "shn.h"
|
||||
|
||||
#define MAGIC "ajkg"
|
||||
#define FORMAT_VERSION 2
|
||||
#define MIN_SUPPORTED_VERSION 1
|
||||
|
@ -155,66 +161,7 @@
|
|||
|
||||
#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*);
|
||||
#define UINT_GET(nbit) \
|
||||
((version == 0) ? uvar_get(nbit) : ulong_get())
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* array.cpp
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Tue Jul 09 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 1992-1995 Tony Robinson *
|
||||
* *
|
||||
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: array.c,v 1.6 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "shn_reader.h"
|
||||
|
||||
void *shn_reader::pmalloc(ulong size) {
|
||||
void *ptr;
|
||||
|
||||
ptr = malloc(size);
|
||||
|
||||
if(ptr == NULL)
|
||||
mFatalError = true;
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
slong **shn_reader::long2d(ulong n0, ulong n1) {
|
||||
slong **array0 = NULL;
|
||||
|
||||
if((array0 = (slong**) pmalloc((ulong) (n0 * sizeof(slong*) +
|
||||
n0 * n1 * sizeof(slong)))) != NULL ) {
|
||||
slong *array1 = (slong*) (array0 + n0);
|
||||
ulong i;
|
||||
|
||||
for(i = 0; i < n0; i++)
|
||||
array0[i] = array1 + i * n1;
|
||||
}
|
||||
return(array0);
|
||||
}
|
||||
|
|
@ -13,6 +13,12 @@
|
|||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* Derek start */
|
||||
pthread_mutex_t mRingLock;
|
||||
pthread_cond_t mRunCond;
|
||||
pthread_t mThread;
|
||||
/* Derek end */
|
||||
|
||||
int shn_seek(shn_file *this_shn, unsigned int time);
|
||||
int shn_seekable(shn_file *this_shn);
|
||||
shn_file *shn_load(char *filename, shn_config config);
|
||||
|
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* fixio.cpp
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Tue Jul 09 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 1992-1995 Tony Robinson *
|
||||
* *
|
||||
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: fixio.c,v 1.6 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "shn_reader.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)
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int Sulaw2linear(uchar);
|
||||
uchar Slinear2ulaw(int);
|
||||
uchar Slinear2alaw(int);
|
||||
}
|
||||
|
||||
void shn_reader::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 shn_reader::fwrite_type_init()
|
||||
{
|
||||
init_sizeof_sample();
|
||||
mDecodeState.writebuf = (char*) NULL;
|
||||
mDecodeState.writefub = (char*) NULL;
|
||||
mDecodeState.nwritebuf = 0;
|
||||
}
|
||||
|
||||
void shn_reader::fwrite_type_quit() {
|
||||
if(mDecodeState.writebuf != NULL) {
|
||||
free(mDecodeState.writebuf);
|
||||
mDecodeState.writebuf = NULL;
|
||||
}
|
||||
if(mDecodeState.writefub != NULL) {
|
||||
free(mDecodeState.writefub);
|
||||
mDecodeState.writefub = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert from signed ints to a given type and write */
|
||||
void shn_reader::fwrite_type(slong **data,int ftype,int nchan,int nitem)
|
||||
{
|
||||
int hiloint = 1, hilo = !(*((char*) &hiloint));
|
||||
int i, nwrite = 0, datasize = sizeof_sample[ftype], chan;
|
||||
slong *data0 = data[0];
|
||||
int bufAvailable = OUT_BUFFER_SIZE - mBytesInBuf;
|
||||
|
||||
if(mDecodeState.nwritebuf < nchan * nitem * datasize) {
|
||||
mDecodeState.nwritebuf = nchan * nitem * datasize;
|
||||
if(mDecodeState.writebuf != NULL) free(mDecodeState.writebuf);
|
||||
if(mDecodeState.writefub != NULL) free(mDecodeState.writefub);
|
||||
mDecodeState.writebuf = (char*) pmalloc((ulong) mDecodeState.nwritebuf);
|
||||
if (!mDecodeState.writebuf)
|
||||
return;
|
||||
mDecodeState.writefub = (char*) pmalloc((ulong) mDecodeState.nwritebuf);
|
||||
if (!mDecodeState.writefub)
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ftype) {
|
||||
case TYPE_AU1: /* leave the conversion to fix_bitshift() */
|
||||
case TYPE_AU2: {
|
||||
uchar *writebufp = (uchar*) mDecodeState.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*) mDecodeState.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*) mDecodeState.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*) mDecodeState.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*) mDecodeState.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*) mDecodeState.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*) mDecodeState.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*) mDecodeState.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 *)&mBuffer[mBytesInBuf],(const void *)mDecodeState.writebuf,datasize*nchan*nitem);
|
||||
mBytesInBuf += datasize*nchan*nitem;
|
||||
nwrite = nitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf(stderr, "Buffer overrun in fwrite_type() [case 1]: %d bytes to read, but only %d bytes are available\n",datasize*nchan*nitem,bufAvailable);
|
||||
}
|
||||
break;
|
||||
case TYPE_S16HL:
|
||||
case TYPE_U16HL:
|
||||
if(hilo)
|
||||
{
|
||||
if (datasize*nchan*nitem <= bufAvailable) {
|
||||
memcpy((void *)&mBuffer[mBytesInBuf],(const void *)mDecodeState.writebuf,datasize*nchan*nitem);
|
||||
mBytesInBuf += datasize*nchan*nitem;
|
||||
nwrite = nitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr, "Buffer overrun in fwrite_type() [case 2]: %d bytes to read, but only %d bytes are available\n",datasize*nchan*nitem,bufAvailable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
swab(mDecodeState.writebuf, mDecodeState.writefub, datasize * nchan * nitem);
|
||||
if (datasize*nchan*nitem <= bufAvailable) {
|
||||
memcpy((void *)&mBuffer[mBytesInBuf],(const void *)mDecodeState.writefub,datasize*nchan*nitem);
|
||||
mBytesInBuf += datasize*nchan*nitem;
|
||||
nwrite = nitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr, "Buffer overrun in fwrite_type() [case 3]: %d bytes to read, but only %d bytes are available\n",datasize*nchan*nitem,bufAvailable);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_S16LH:
|
||||
case TYPE_U16LH:
|
||||
if(hilo)
|
||||
{
|
||||
swab(mDecodeState.writebuf, mDecodeState.writefub, datasize * nchan * nitem);
|
||||
if (datasize*nchan*nitem <= bufAvailable) {
|
||||
memcpy((void *)&mBuffer[mBytesInBuf],(const void *)mDecodeState.writefub,datasize*nchan*nitem);
|
||||
mBytesInBuf += datasize*nchan*nitem;
|
||||
nwrite = nitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr, "Buffer overrun in fwrite_type() [case 4]: %d bytes to read, but only %d bytes are available\n",datasize*nchan*nitem,bufAvailable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (datasize*nchan*nitem <= bufAvailable) {
|
||||
memcpy((void *)&mBuffer[mBytesInBuf],(const void *)mDecodeState.writebuf,datasize*nchan*nitem);
|
||||
mBytesInBuf += datasize*nchan*nitem;
|
||||
nwrite = nitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr, "Buffer overrun in fwrite_type() [case 5]: %d bytes to read, but only %d bytes are available\n",datasize*nchan*nitem,bufAvailable);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(nwrite != nitem)
|
||||
{
|
||||
mFatalError = true;
|
||||
//fprintf(stderr,"Failed to write decompressed stream -\npossible corrupt or truncated file\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*************/
|
||||
/* bitshifts */
|
||||
/*************/
|
||||
|
||||
void shn_reader::fix_bitshift(slong *buffer, int nitem, int bitshift, int 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;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
Millennium Sound System
|
||||
©1999-2000 Subband Software, Inc.
|
||||
|
||||
Description: GP Ring Buffer class
|
||||
Released: 9/15/99
|
||||
|
||||
Version history:
|
||||
|
||||
Date Who Changes
|
||||
--------+---------+------------------------------------------------------
|
||||
06-19-00 AVL parameter types changes, conflicting function names fixed,
|
||||
IsFreeSpace() changed to IsReadMode(), ReadDataCR() removed.
|
||||
09-15-99 DAB Initial release.
|
||||
|
||||
DAB = Dmitry Boldyrev
|
||||
AVL = Alex Lagutin
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "ringbuffer.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
RingBuffer::RingBuffer()
|
||||
{
|
||||
mFreeSpace=0;
|
||||
mBuffer=NULL;
|
||||
|
||||
mBufSize=0;
|
||||
mBufRdIdx=0;
|
||||
mBufWxIdx=0;
|
||||
|
||||
mSaveFreeSpace=-1;
|
||||
}
|
||||
|
||||
int RingBuffer::Init(long inSize)
|
||||
{
|
||||
mBufSize=inSize;
|
||||
if (mBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
if ((mBuffer = new char[mBufSize]) == NULL)
|
||||
return -1;
|
||||
|
||||
Empty();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
RingBuffer::Empty()
|
||||
{
|
||||
mBufRdIdx=0;
|
||||
mBufWxIdx=0;
|
||||
mFreeSpace=mBufSize;
|
||||
mSaveFreeSpace=-1;
|
||||
|
||||
// if (mBuffer) {
|
||||
// memset(mBuffer, 0, mBufSize);
|
||||
// }
|
||||
}
|
||||
|
||||
RingBuffer::~RingBuffer()
|
||||
{
|
||||
if (mBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
mBuffer=NULL;
|
||||
}
|
||||
|
||||
|
||||
long RingBuffer::WriteData(char *data, long len)
|
||||
{
|
||||
int written, before;
|
||||
|
||||
if (!mBufSize || data==NULL || !mBuffer)
|
||||
return 0;
|
||||
|
||||
written=0;
|
||||
if (!(len = MIN(FreeSpace(false), len)))
|
||||
return 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (len + mBufWxIdx < mBufSize)
|
||||
{
|
||||
::memcpy(&mBuffer[mBufWxIdx], &data[written], (size_t) len);
|
||||
mBufWxIdx += len;
|
||||
written += len;
|
||||
mFreeSpace -= len;
|
||||
if (mSaveFreeSpace != -1)
|
||||
mSaveFreeSpace -= len;
|
||||
|
||||
return written;
|
||||
} else
|
||||
{
|
||||
before = mBufSize - mBufWxIdx;
|
||||
::memcpy(&mBuffer[mBufWxIdx], &data[written], (size_t) before);
|
||||
written += before;
|
||||
len -= before;
|
||||
mFreeSpace -= before;
|
||||
if (mSaveFreeSpace != -1)
|
||||
mSaveFreeSpace -= before;
|
||||
|
||||
mBufWxIdx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RingBuffer::SaveRead()
|
||||
{
|
||||
if (mSaveFreeSpace!=-1)
|
||||
return;
|
||||
mSaveReadPos=mBufRdIdx;
|
||||
mSaveFreeSpace=mFreeSpace;
|
||||
}
|
||||
|
||||
void RingBuffer::RestoreRead()
|
||||
{
|
||||
if (mSaveFreeSpace==-1)
|
||||
return;
|
||||
mBufRdIdx=mSaveReadPos;
|
||||
mFreeSpace=mSaveFreeSpace;
|
||||
mSaveFreeSpace=-1;
|
||||
}
|
||||
|
||||
long RingBuffer::ReadData(char *data, long len)
|
||||
{
|
||||
int read, before;
|
||||
|
||||
if (!mBufSize) return 0;
|
||||
|
||||
read = 0;
|
||||
if (!(len = MIN(UsedSpace(true), len)))
|
||||
return 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (len + mBufRdIdx < mBufSize)
|
||||
{
|
||||
if (data) {
|
||||
::memcpy(&data[read], &mBuffer[mBufRdIdx], (size_t) len);
|
||||
}
|
||||
mBufRdIdx += len;
|
||||
read += len;
|
||||
mFreeSpace += len;
|
||||
|
||||
return read;
|
||||
} else
|
||||
{
|
||||
before = mBufSize - mBufRdIdx;
|
||||
if (data) {
|
||||
::memcpy(&data[read], &mBuffer[mBufRdIdx], (size_t) before);
|
||||
}
|
||||
read += before;
|
||||
len -= before;
|
||||
mFreeSpace += before;
|
||||
|
||||
mBufRdIdx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long RingBuffer::FreeSpace(bool inTrueSpace)
|
||||
{
|
||||
if (inTrueSpace)
|
||||
return mFreeSpace;
|
||||
else
|
||||
return (mSaveFreeSpace==-1) ? mFreeSpace : mSaveFreeSpace;
|
||||
}
|
||||
|
||||
long RingBuffer::UsedSpace(bool inTrueSpace)
|
||||
{
|
||||
if (inTrueSpace)
|
||||
return (mBufSize - mFreeSpace);
|
||||
else
|
||||
return (mSaveFreeSpace==-1) ? (mBufSize - mFreeSpace) :
|
||||
(mBufSize - mSaveFreeSpace);
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* seek.cpp
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Tue Jul 09 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/* seek.c - functions related to real-time seeking
|
||||
* Copyright (C) 2000-2001 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: seek.c,v 1.4 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "shn_reader.h"
|
||||
|
||||
#define SEEK_HEADER_SIGNATURE "SEEK"
|
||||
#define SEEK_TRAILER_SIGNATURE "SHNAMPSK"
|
||||
#define SEEK_SUFFIX ".skt"
|
||||
|
||||
shn_seek_entry *shn_reader::seek_entry_search(ulong goal, ulong min, ulong max)
|
||||
{
|
||||
ulong med = (min + max) / 2;
|
||||
shn_seek_entry *middle = &mSeekTable[med];
|
||||
ulong sample = uchar_to_ulong_le(middle->data);
|
||||
|
||||
if (goal < sample)
|
||||
return seek_entry_search(goal, min, med-1);
|
||||
if (goal > sample + 25600)
|
||||
return seek_entry_search(goal, med+1, max);
|
||||
|
||||
return middle;
|
||||
}
|
||||
|
||||
void shn_reader::load_seek_table(const char *fn)
|
||||
{
|
||||
FILE *fp;
|
||||
int found = 0;
|
||||
|
||||
if (!(fp = fopen(fn, "r")))
|
||||
return;
|
||||
|
||||
fseek(fp, -SEEK_TRAILER_SIZE, SEEK_END);
|
||||
if (fread(mSeekTrailer.data, 1, SEEK_TRAILER_SIZE, fp) == SEEK_TRAILER_SIZE)
|
||||
{
|
||||
mSeekTrailer.seekTableSize = uchar_to_ulong_le(mSeekTrailer.data);
|
||||
if (!memcmp(&mSeekTrailer.data[4], SEEK_TRAILER_SIGNATURE, strlen(SEEK_TRAILER_SIGNATURE)))
|
||||
{
|
||||
fseek(fp, -mSeekTrailer.seekTableSize, SEEK_END);
|
||||
mSeekTrailer.seekTableSize -= (SEEK_HEADER_SIZE + SEEK_TRAILER_SIZE);
|
||||
if (fread(mSeekHeader.data, 1, SEEK_HEADER_SIZE, fp) == SEEK_HEADER_SIZE)
|
||||
{
|
||||
long entries = mSeekTrailer.seekTableSize/sizeof(shn_seek_entry);
|
||||
|
||||
if ((mSeekTable = (shn_seek_entry *) malloc(sizeof(shn_seek_entry)*entries)))
|
||||
{
|
||||
if ((long)fread(mSeekTable, sizeof(shn_seek_entry), entries, fp) == entries)
|
||||
{
|
||||
//fprintf(stderr, "Successfully loaded seek table appended to file: '%s'\n", fn);
|
||||
mSeekTableEntries = entries;
|
||||
found = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(mSeekTable);
|
||||
mSeekTable = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (found)
|
||||
return;
|
||||
|
||||
{
|
||||
// try load from separate seek file
|
||||
char *slash, *ext;
|
||||
char seek_fn[MAX_PATH];
|
||||
|
||||
strcpy(seek_fn, fn);
|
||||
slash = strrchr(seek_fn, '/');
|
||||
ext = strrchr((slash ? slash : seek_fn), '.');
|
||||
if (ext)
|
||||
*ext = 0;
|
||||
strcat(seek_fn, SEEK_SUFFIX);
|
||||
load_separate_seek_table(seek_fn);
|
||||
}
|
||||
}
|
||||
|
||||
int shn_reader::load_separate_seek_table(const char *fn)
|
||||
{
|
||||
FILE *fp;
|
||||
long seek_table_len, entries;
|
||||
int result = 0;
|
||||
|
||||
//fprintf(stderr, "Looking for seek table in separate file: '%s'\n", fn);
|
||||
|
||||
if (!(fp = fopen(fn, "r")))
|
||||
return 0;
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
seek_table_len = (long)ftell(fp) - SEEK_HEADER_SIZE;
|
||||
entries = seek_table_len/sizeof(shn_seek_entry);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (fread(mSeekHeader.data, 1, SEEK_HEADER_SIZE, fp) == SEEK_HEADER_SIZE)
|
||||
{
|
||||
mSeekHeader.version = uchar_to_ulong_le(&mSeekHeader.data[4]);
|
||||
mSeekHeader.shnFileSize = uchar_to_ulong_le(&mSeekHeader.data[8]);
|
||||
if (!memcmp(mSeekHeader.data, SEEK_HEADER_SIGNATURE, strlen(SEEK_HEADER_SIGNATURE)))
|
||||
{
|
||||
if (mSeekHeader.shnFileSize == mWAVEHeader.actual_size)
|
||||
{
|
||||
if ((mSeekTable = (shn_seek_entry *) malloc(sizeof(shn_seek_entry)*entries)))
|
||||
{
|
||||
if ((long)fread(mSeekTable, sizeof(shn_seek_entry), entries, fp) == entries)
|
||||
{
|
||||
//fprintf(stderr, "Successfully loaded seek table in separate file: '%s'\n", fn);
|
||||
mSeekTableEntries = entries;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(mSeekTable);
|
||||
mSeekTable = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr, "Seek table .shn file size and actual .shn file size differ\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* shn_reader.cpp
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Sun Jul 07 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/* shn.c - main functions for xmms-shn
|
||||
* Copyright (C) 2000-2001 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: shn.c,v 1.9 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
#include "shn_reader.h"
|
||||
|
||||
#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 WAVE_FORMAT_PCM (0x0001)
|
||||
#define CANONICAL_HEADER_SIZE (44)
|
||||
|
||||
#define CACHE_SIZE (256*1024) //256K
|
||||
|
||||
static 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\n", ftype);
|
||||
break;
|
||||
}
|
||||
|
||||
for(chan = 0; chan < nchan; chan++)
|
||||
for(i = 0; i < nblock; i++)
|
||||
offset[chan][i] = mean;
|
||||
}
|
||||
|
||||
shn_reader::shn_reader()
|
||||
{
|
||||
init();
|
||||
pthread_mutex_init(&mRingLock, NULL);
|
||||
pthread_cond_init(&mRunCond, NULL);
|
||||
}
|
||||
|
||||
shn_reader::~shn_reader()
|
||||
{
|
||||
exit();
|
||||
pthread_mutex_destroy(&mRingLock);
|
||||
pthread_cond_destroy(&mRunCond);
|
||||
}
|
||||
|
||||
void shn_reader::init()
|
||||
{
|
||||
mSeekTable = NULL;
|
||||
mSeekTo = -1;
|
||||
mFP = NULL;
|
||||
mFatalError = false;
|
||||
mGoing = false;
|
||||
mEOF = false;
|
||||
memset(&mDecodeState, 0, sizeof(mDecodeState));
|
||||
memset(&mWAVEHeader, 0, sizeof(mWAVEHeader));
|
||||
mRing.Init(CACHE_SIZE);
|
||||
}
|
||||
|
||||
void shn_reader::exit()
|
||||
{
|
||||
if (mGoing)
|
||||
{
|
||||
mGoing = false;
|
||||
pthread_cond_signal(&mRunCond);
|
||||
pthread_join(mThread, NULL);
|
||||
}
|
||||
|
||||
if (mDecodeState.getbuf)
|
||||
{
|
||||
free(mDecodeState.getbuf);
|
||||
mDecodeState.getbuf = NULL;
|
||||
}
|
||||
if (mDecodeState.writebuf)
|
||||
{
|
||||
free(mDecodeState.writebuf);
|
||||
mDecodeState.writebuf = NULL;
|
||||
}
|
||||
if (mDecodeState.writefub)
|
||||
{
|
||||
free(mDecodeState.writefub);
|
||||
mDecodeState.writefub = NULL;
|
||||
}
|
||||
if (mSeekTable)
|
||||
{
|
||||
free(mSeekTable);
|
||||
mSeekTable = NULL;
|
||||
}
|
||||
if (mFP)
|
||||
{
|
||||
fclose(mFP);
|
||||
mFP = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int shn_reader::open(const char *fn, bool should_load_seek_table)
|
||||
{
|
||||
struct stat sz;
|
||||
|
||||
exit();
|
||||
init();
|
||||
|
||||
if (stat(fn, &sz))
|
||||
return -1;
|
||||
|
||||
if (!S_ISREG(sz.st_mode))
|
||||
return -1;
|
||||
|
||||
mWAVEHeader.actual_size = (ulong)sz.st_size;
|
||||
|
||||
mFP = fopen(fn, "r");
|
||||
|
||||
if (!mFP)
|
||||
return -1;
|
||||
|
||||
if (!get_wave_header() || !verify_header())
|
||||
{
|
||||
fclose(mFP);
|
||||
mFP = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (should_load_seek_table)
|
||||
load_seek_table(fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shn_reader::go()
|
||||
{
|
||||
if (!mFP)
|
||||
return -1;
|
||||
|
||||
fseek(mFP, 0, SEEK_SET);
|
||||
mGoing = true;
|
||||
|
||||
if (pthread_create(&mThread, NULL, (void *(*)(void *))thread_runner, this))
|
||||
{
|
||||
mGoing = false;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long shn_reader::read(void *buf, long size)
|
||||
{
|
||||
long actread;
|
||||
|
||||
if (!mGoing)
|
||||
return -2;
|
||||
|
||||
pthread_mutex_lock(&mRingLock);
|
||||
actread = mRing.ReadData((char *) buf, size);
|
||||
if (!actread)
|
||||
actread = mEOF ? -2 : -1;
|
||||
|
||||
pthread_mutex_unlock(&mRingLock);
|
||||
if (actread > 0)
|
||||
pthread_cond_signal(&mRunCond);
|
||||
|
||||
return actread;
|
||||
}
|
||||
|
||||
float shn_reader::seek(float seconds)
|
||||
{
|
||||
if (!mSeekTable)
|
||||
return -1.0f;
|
||||
|
||||
mSeekTo = (int) seconds;
|
||||
shn_seek_entry *seek_info = seek_entry_search(mSeekTo * (ulong)mWAVEHeader.samples_per_sec,0,
|
||||
(ulong)(mSeekTableEntries - 1));
|
||||
ulong sample = uchar_to_ulong_le(seek_info->data);
|
||||
return (float)sample/((float)mWAVEHeader.samples_per_sec);
|
||||
}
|
||||
|
||||
int shn_reader::shn_get_buffer_block_size(int blocks)//derek
|
||||
{
|
||||
int blk_size = blocks * (mWAVEHeader.bits_per_sample / 8) * mWAVEHeader.channels;
|
||||
if(blk_size > OUT_BUFFER_SIZE)
|
||||
{
|
||||
blk_size = NUM_DEFAULT_BUFFER_BLOCKS * (mWAVEHeader.bits_per_sample / 8) * mWAVEHeader.channels;
|
||||
}
|
||||
|
||||
return blk_size;
|
||||
}
|
||||
|
||||
unsigned int shn_reader::shn_get_song_length()//derek
|
||||
{
|
||||
if(mWAVEHeader.length > 0)
|
||||
return (unsigned int)(1000 * mWAVEHeader.length);
|
||||
|
||||
/* Something failed or just isn't correct */
|
||||
return (unsigned int)0;
|
||||
}
|
||||
|
||||
bool shn_reader::file_info(long *size, int *nch, float *rate, float *time,
|
||||
int *samplebits, bool *seekable)
|
||||
{
|
||||
float frate;
|
||||
int frame_size;
|
||||
|
||||
if (!mFP)
|
||||
return false;
|
||||
|
||||
if (seekable)
|
||||
*seekable = mSeekTable ? true : false;
|
||||
|
||||
if (size)
|
||||
*size = mWAVEHeader.actual_size;
|
||||
|
||||
if (nch)
|
||||
*nch = mWAVEHeader.channels;
|
||||
|
||||
frame_size = (uint)mWAVEHeader.channels * (uint)mWAVEHeader.bits_per_sample / 8;
|
||||
frate = (float)mWAVEHeader.samples_per_sec;
|
||||
|
||||
if (rate)
|
||||
*rate = frate;
|
||||
|
||||
if (time)
|
||||
*time = (float)mWAVEHeader.data_size/((float)frame_size * frate);
|
||||
|
||||
if (samplebits)
|
||||
*samplebits = mWAVEHeader.bits_per_sample;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void shn_reader::init_decode_state()
|
||||
{
|
||||
if (mDecodeState.getbuf)
|
||||
free(mDecodeState.getbuf);
|
||||
|
||||
if (mDecodeState.writebuf)
|
||||
free(mDecodeState.writebuf);
|
||||
|
||||
if (mDecodeState.writefub)
|
||||
free(mDecodeState.writefub);
|
||||
|
||||
memset(&mDecodeState, 0, sizeof(mDecodeState));
|
||||
}
|
||||
|
||||
int shn_reader::get_wave_header()
|
||||
{
|
||||
int version = FORMAT_VERSION;
|
||||
int ftype = TYPE_EOF;
|
||||
char *magic = MAGIC;
|
||||
int internal_ftype;
|
||||
int retval = 1;
|
||||
|
||||
init_decode_state();
|
||||
mBytesInHeader = 0;
|
||||
/***********************/
|
||||
/* EXTRACT starts here */
|
||||
/***********************/
|
||||
|
||||
/* read magic number */
|
||||
#ifdef STRICT_FORMAT_COMPATABILITY
|
||||
if(FORMAT_VERSION < 2)
|
||||
{
|
||||
for(int i = 0; i < strlen(magic); i++)
|
||||
if(getc(mFP) != magic[i])
|
||||
return 0;
|
||||
|
||||
/* get version number */
|
||||
version = getc(mFP);
|
||||
if (version == EOF)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
#endif /* STRICT_FORMAT_COMPATABILITY */
|
||||
{
|
||||
int nscan = 0;
|
||||
|
||||
version = MAX_VERSION + 1;
|
||||
while(version > MAX_VERSION)
|
||||
{
|
||||
int byte = getc(mFP);
|
||||
if(byte == EOF)
|
||||
return 0;
|
||||
if(magic[nscan] != '\0' && byte == magic[nscan])
|
||||
nscan++;
|
||||
else
|
||||
if(magic[nscan] == '\0' && byte <= MAX_VERSION)
|
||||
version = byte;
|
||||
else
|
||||
{
|
||||
if(byte == magic[0])
|
||||
nscan = 1;
|
||||
else
|
||||
{
|
||||
nscan = 0;
|
||||
}
|
||||
version = MAX_VERSION + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check version number */
|
||||
if(version > MAX_SUPPORTED_VERSION)
|
||||
return 0;
|
||||
|
||||
/* initialise the variable length file read for the compressed stream */
|
||||
var_get_init();
|
||||
if (mFatalError)
|
||||
return 0;
|
||||
|
||||
/* get the internal file type */
|
||||
internal_ftype = UINT_GET(TYPESIZE);
|
||||
|
||||
/* has the user requested a change in file type? */
|
||||
if(internal_ftype != ftype) {
|
||||
if(ftype == TYPE_EOF)
|
||||
ftype = internal_ftype; /* no problems here */
|
||||
else /* check that the requested conversion is valid */
|
||||
if(internal_ftype == TYPE_AU1 || internal_ftype == TYPE_AU2 ||
|
||||
internal_ftype == TYPE_AU3 || ftype == TYPE_AU1 ||ftype == TYPE_AU2 || ftype == TYPE_AU3)
|
||||
goto got_enough_data;
|
||||
}
|
||||
|
||||
UINT_GET(CHANSIZE);
|
||||
|
||||
/* get blocksize if version > 0 */
|
||||
if(version > 0)
|
||||
{
|
||||
int byte, nskip;
|
||||
UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2));
|
||||
UINT_GET(LPCQSIZE);
|
||||
UINT_GET(0);
|
||||
nskip = UINT_GET(NSKIPSIZE);
|
||||
for(int i = 0; i < nskip; i++)
|
||||
{
|
||||
byte = uvar_get(XBYTESIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* find verbatim command */
|
||||
while(1)
|
||||
{
|
||||
int cmd = uvar_get(FNSIZE);
|
||||
switch(cmd)
|
||||
{
|
||||
case FN_VERBATIM:
|
||||
{
|
||||
int cklen = uvar_get(VERBATIM_CKSIZE_SIZE);
|
||||
|
||||
while (cklen--)
|
||||
{
|
||||
if (mBytesInHeader >= OUT_BUFFER_SIZE)
|
||||
{
|
||||
retval = 0;
|
||||
goto got_enough_data;
|
||||
}
|
||||
mBytesInBuf = 0;
|
||||
mHeader[mBytesInHeader++] = (unsigned char)uvar_get(VERBATIM_BYTE_SIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto got_enough_data;
|
||||
}
|
||||
}
|
||||
|
||||
got_enough_data:
|
||||
|
||||
/* wind up */
|
||||
var_get_quit();
|
||||
|
||||
mBytesInBuf = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int shn_reader::verify_header()
|
||||
{
|
||||
ulong l;
|
||||
int cur = 0;
|
||||
|
||||
if (mBytesInHeader < CANONICAL_HEADER_SIZE)
|
||||
return 0;
|
||||
|
||||
if (WAVE_RIFF != uchar_to_ulong_le(&mHeader[cur]))
|
||||
return 0;
|
||||
cur += 4;
|
||||
|
||||
mWAVEHeader.chunk_size = uchar_to_ulong_le(&mHeader[cur]);
|
||||
cur += 4;
|
||||
|
||||
if (WAVE_WAVE != uchar_to_ulong_le(&mHeader[cur]))
|
||||
return 0;
|
||||
cur += 4;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
cur += 4;
|
||||
|
||||
l = uchar_to_ulong_le(&mHeader[cur]);
|
||||
cur += 4;
|
||||
|
||||
if (WAVE_FMT == uchar_to_ulong_le(&mHeader[cur-8]))
|
||||
break;
|
||||
|
||||
cur += l;
|
||||
}
|
||||
|
||||
if (l < 16)
|
||||
return 0;
|
||||
|
||||
mWAVEHeader.wave_format = uchar_to_ushort_le(&mHeader[cur]);
|
||||
cur += 2;
|
||||
|
||||
switch (mWAVEHeader.wave_format)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
mWAVEHeader.channels = uchar_to_ushort_le(&mHeader[cur]);
|
||||
cur += 2;
|
||||
mWAVEHeader.samples_per_sec = uchar_to_ulong_le(&mHeader[cur]);
|
||||
cur += 4;
|
||||
mWAVEHeader.avg_bytes_per_sec = uchar_to_ulong_le(&mHeader[cur]);
|
||||
cur += 4;
|
||||
mWAVEHeader.block_align = uchar_to_ushort_le(&mHeader[cur]);
|
||||
cur += 2;
|
||||
mWAVEHeader.bits_per_sample = uchar_to_ushort_le(&mHeader[cur]);
|
||||
cur += 2;
|
||||
|
||||
if (mWAVEHeader.bits_per_sample != 8 && mWAVEHeader.bits_per_sample != 16)
|
||||
return 0;
|
||||
|
||||
l -= 16;
|
||||
|
||||
if (l > 0)
|
||||
cur += l;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
cur += 4;
|
||||
|
||||
l = uchar_to_ulong_le(&mHeader[cur]);
|
||||
cur += 4;
|
||||
|
||||
if (WAVE_DATA == uchar_to_ulong_le(&mHeader[cur-8]))
|
||||
break;
|
||||
|
||||
cur += l;
|
||||
}
|
||||
|
||||
mWAVEHeader.rate = ((uint)mWAVEHeader.samples_per_sec *
|
||||
(uint)mWAVEHeader.channels *
|
||||
(uint)mWAVEHeader.bits_per_sample) / 8;
|
||||
mWAVEHeader.header_size = cur;
|
||||
mWAVEHeader.data_size = l;
|
||||
mWAVEHeader.total_size = mWAVEHeader.chunk_size + 8;
|
||||
mWAVEHeader.length = mWAVEHeader.data_size / mWAVEHeader.rate;
|
||||
|
||||
/* header looks ok */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shn_reader::write_and_wait(int block_size)
|
||||
{
|
||||
int bytes_to_write;
|
||||
|
||||
if (mBytesInBuf < block_size)
|
||||
return;
|
||||
|
||||
bytes_to_write = MIN(mBytesInBuf, block_size);
|
||||
|
||||
if (bytes_to_write <= 0)
|
||||
return;
|
||||
|
||||
while (mGoing && mSeekTo == -1)
|
||||
{
|
||||
long written;
|
||||
|
||||
pthread_mutex_lock(&mRingLock);
|
||||
written = mRing.WriteData((char *) mBuffer, bytes_to_write);
|
||||
bytes_to_write -= written;
|
||||
mBytesInBuf -= written;
|
||||
if (!bytes_to_write)
|
||||
{
|
||||
pthread_mutex_unlock(&mRingLock);
|
||||
break;
|
||||
}
|
||||
pthread_cond_wait(&mRunCond, &mRingLock);
|
||||
pthread_mutex_unlock(&mRingLock);
|
||||
}
|
||||
}
|
||||
|
||||
void shn_reader::Run()
|
||||
{
|
||||
slong **buffer = NULL, **offset = NULL;
|
||||
slong lpcqoffset = 0;
|
||||
int version = FORMAT_VERSION, bitshift = 0;
|
||||
int ftype = TYPE_EOF;
|
||||
char *magic = MAGIC;
|
||||
int blocksize = DEFAULT_BLOCK_SIZE, nchan = DEFAULT_NCHAN;
|
||||
int i, chan, nwrap, nskip = DEFAULT_NSKIP;
|
||||
int *qlpc = NULL, maxnlpc = DEFAULT_MAXNLPC, nmean = UNDEFINED_UINT;
|
||||
int cmd;
|
||||
int internal_ftype;
|
||||
int blk_size;
|
||||
int cklen;
|
||||
uchar tmp;
|
||||
|
||||
restart:
|
||||
|
||||
mBytesInBuf = 0;
|
||||
|
||||
init_decode_state();
|
||||
|
||||
blk_size = 512 * (mWAVEHeader.bits_per_sample / 8) * mWAVEHeader.channels;
|
||||
|
||||
/***********************/
|
||||
/* EXTRACT starts here */
|
||||
/***********************/
|
||||
|
||||
/* read magic number */
|
||||
#ifdef STRICT_FORMAT_COMPATABILITY
|
||||
if(FORMAT_VERSION < 2)
|
||||
{
|
||||
for(i = 0; i < strlen(magic); i++)
|
||||
if(getc(this_shn->vars.fd) != magic[i])
|
||||
{
|
||||
mFatalError = true;
|
||||
goto exit_thread;
|
||||
}
|
||||
|
||||
/* get version number */
|
||||
version = getc(this_shn->vars.fd);
|
||||
if (version == EOF)
|
||||
{
|
||||
mFatalError = true;
|
||||
goto exit_thread;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* STRICT_FORMAT_COMPATABILITY */
|
||||
{
|
||||
int nscan = 0;
|
||||
|
||||
version = MAX_VERSION + 1;
|
||||
while(version > MAX_VERSION)
|
||||
{
|
||||
int byte = getc(mFP);
|
||||
if(byte == EOF) {
|
||||
mFatalError = true;
|
||||
goto exit_thread;
|
||||
}
|
||||
if(magic[nscan] != '\0' && byte == magic[nscan])
|
||||
nscan++;
|
||||
else
|
||||
if(magic[nscan] == '\0' && byte <= MAX_VERSION)
|
||||
version = byte;
|
||||
else
|
||||
{
|
||||
if(byte == magic[0])
|
||||
nscan = 1;
|
||||
else
|
||||
{
|
||||
nscan = 0;
|
||||
}
|
||||
version = MAX_VERSION + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check version number */
|
||||
if(version > MAX_SUPPORTED_VERSION) {
|
||||
mFatalError = true;
|
||||
goto exit_thread;
|
||||
}
|
||||
|
||||
/* set up the default nmean, ignoring the command line state */
|
||||
nmean = (version < 2) ? DEFAULT_V0NMEAN : DEFAULT_V2NMEAN;
|
||||
|
||||
/* initialise the variable length file read for the compressed stream */
|
||||
var_get_init();
|
||||
if (mFatalError)
|
||||
goto exit_thread;
|
||||
|
||||
/* initialise the fixed length file write for the uncompressed stream */
|
||||
fwrite_type_init();
|
||||
|
||||
/* get the internal file type */
|
||||
internal_ftype = UINT_GET(TYPESIZE);
|
||||
|
||||
/* has the user requested a change in file type? */
|
||||
if(internal_ftype != ftype) {
|
||||
if(ftype == TYPE_EOF)
|
||||
ftype = internal_ftype; /* no problems here */
|
||||
else /* check that the requested conversion is valid */
|
||||
if(internal_ftype == TYPE_AU1 || internal_ftype == TYPE_AU2 ||
|
||||
internal_ftype == TYPE_AU3 || ftype == TYPE_AU1 ||ftype == TYPE_AU2 || ftype == TYPE_AU3) {
|
||||
mFatalError = true;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
nchan = UINT_GET(CHANSIZE);
|
||||
|
||||
/* get blocksize if version > 0 */
|
||||
if(version > 0)
|
||||
{
|
||||
int byte;
|
||||
blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2));
|
||||
maxnlpc = UINT_GET(LPCQSIZE);
|
||||
nmean = UINT_GET(0);
|
||||
nskip = UINT_GET(NSKIPSIZE);
|
||||
for(i = 0; i < nskip; i++)
|
||||
{
|
||||
byte = uvar_get(XBYTESIZE);
|
||||
}
|
||||
}
|
||||
else
|
||||
blocksize = DEFAULT_BLOCK_SIZE;
|
||||
|
||||
nwrap = MAX(NWRAP, maxnlpc);
|
||||
|
||||
/* grab some space for the input buffer */
|
||||
buffer = long2d((ulong) nchan, (ulong) (blocksize + nwrap));
|
||||
if (mFatalError)
|
||||
goto exit_thread;
|
||||
offset = long2d((ulong) nchan, (ulong) MAX(1, nmean));
|
||||
if (mFatalError) {
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
goto exit_thread;
|
||||
}
|
||||
|
||||
for(chan = 0; chan < nchan; chan++)
|
||||
{
|
||||
for(i = 0; i < nwrap; i++)
|
||||
buffer[chan][i] = 0;
|
||||
buffer[chan] += nwrap;
|
||||
}
|
||||
|
||||
if(maxnlpc > 0) {
|
||||
qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc)));
|
||||
if (mFatalError) {
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
if (offset) {
|
||||
free(offset);
|
||||
buffer = NULL;
|
||||
}
|
||||
goto exit_thread;
|
||||
}
|
||||
}
|
||||
|
||||
if(version > 1)
|
||||
lpcqoffset = V2LPCQOFFSET;
|
||||
|
||||
init_offset(offset, nchan, MAX(1, nmean), internal_ftype);
|
||||
|
||||
/* get commands from file and execute them */
|
||||
chan = 0;
|
||||
while(1)
|
||||
{
|
||||
cmd = uvar_get(FNSIZE);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case FN_ZERO:
|
||||
case FN_DIFF0:
|
||||
case FN_DIFF1:
|
||||
case FN_DIFF2:
|
||||
case FN_DIFF3:
|
||||
case FN_QLPC:
|
||||
{
|
||||
slong coffset, *cbuffer = buffer[chan];
|
||||
int resn = 0, nlpc, j;
|
||||
|
||||
if(cmd != FN_ZERO)
|
||||
{
|
||||
resn = uvar_get(ENERGYSIZE);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
/* this is a hack as version 0 differed in definition of var_get */
|
||||
if(version == 0)
|
||||
resn--;
|
||||
}
|
||||
|
||||
/* find mean offset : N.B. this code duplicated */
|
||||
if(nmean == 0)
|
||||
coffset = offset[chan][0];
|
||||
else
|
||||
{
|
||||
slong sum = (version < 2) ? 0 : nmean / 2;
|
||||
for(i = 0; i < nmean; i++)
|
||||
sum += offset[chan][i];
|
||||
if(version < 2)
|
||||
coffset = sum / nmean;
|
||||
else
|
||||
coffset = ROUNDEDSHIFTDOWN(sum / nmean, bitshift);
|
||||
}
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case FN_ZERO:
|
||||
for(i = 0; i < blocksize; i++)
|
||||
cbuffer[i] = 0;
|
||||
break;
|
||||
case FN_DIFF0:
|
||||
for(i = 0; i < blocksize; i++) {
|
||||
cbuffer[i] = var_get(resn) + coffset;
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case FN_DIFF1:
|
||||
for(i = 0; i < blocksize; i++) {
|
||||
cbuffer[i] = var_get(resn) + cbuffer[i - 1];
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case FN_DIFF2:
|
||||
for(i = 0; i < blocksize; i++) {
|
||||
cbuffer[i] = var_get(resn) + (2 * cbuffer[i - 1] - cbuffer[i - 2]);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case FN_DIFF3:
|
||||
for(i = 0; i < blocksize; i++) {
|
||||
cbuffer[i] = var_get(resn) + 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3];
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case FN_QLPC:
|
||||
nlpc = uvar_get(LPCQSIZE);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
|
||||
for(i = 0; i < nlpc; i++) {
|
||||
qlpc[i] = var_get(LPCQUANT);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
for(i = 0; i < nlpc; i++)
|
||||
cbuffer[i - nlpc] -= coffset;
|
||||
for(i = 0; i < blocksize; i++)
|
||||
{
|
||||
slong sum = lpcqoffset;
|
||||
|
||||
for(j = 0; j < nlpc; j++)
|
||||
sum += qlpc[j] * cbuffer[i - j - 1];
|
||||
cbuffer[i] = var_get(resn) + (sum >> LPCQUANT);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
if(coffset != 0)
|
||||
for(i = 0; i < blocksize; i++)
|
||||
cbuffer[i] += coffset;
|
||||
break;
|
||||
}
|
||||
|
||||
/* store mean value if appropriate : N.B. Duplicated code */
|
||||
if(nmean > 0)
|
||||
{
|
||||
slong sum = (version < 2) ? 0 : blocksize / 2;
|
||||
|
||||
for(i = 0; i < blocksize; i++)
|
||||
sum += cbuffer[i];
|
||||
|
||||
for(i = 1; i < nmean; i++)
|
||||
offset[chan][i - 1] = offset[chan][i];
|
||||
if(version < 2)
|
||||
offset[chan][nmean - 1] = sum / blocksize;
|
||||
else
|
||||
offset[chan][nmean - 1] = (sum / blocksize) << bitshift;
|
||||
}
|
||||
|
||||
/* do the wrap */
|
||||
for(i = -nwrap; i < 0; i++)
|
||||
cbuffer[i] = cbuffer[i + blocksize];
|
||||
|
||||
fix_bitshift(cbuffer, blocksize, bitshift, internal_ftype);
|
||||
|
||||
if(chan == nchan - 1)
|
||||
{
|
||||
if (!mGoing || mFatalError)
|
||||
goto cleanup;
|
||||
|
||||
fwrite_type(buffer, ftype, nchan, blocksize);
|
||||
|
||||
write_and_wait(blk_size);
|
||||
|
||||
if (mSeekTo != -1)
|
||||
{
|
||||
shn_seek_entry *seek_info = seek_entry_search(mSeekTo * (ulong)mWAVEHeader.samples_per_sec,0,
|
||||
(ulong)(mSeekTableEntries - 1));
|
||||
|
||||
pthread_mutex_lock(&mRingLock);
|
||||
mRing.Empty();
|
||||
pthread_mutex_unlock(&mRingLock);
|
||||
|
||||
buffer[0][-1] = uchar_to_slong_le(seek_info->data+24);
|
||||
buffer[0][-2] = uchar_to_slong_le(seek_info->data+28);
|
||||
buffer[0][-3] = uchar_to_slong_le(seek_info->data+32);
|
||||
offset[0][0] = uchar_to_slong_le(seek_info->data+48);
|
||||
offset[0][1] = uchar_to_slong_le(seek_info->data+52);
|
||||
offset[0][2] = uchar_to_slong_le(seek_info->data+56);
|
||||
offset[0][3] = uchar_to_slong_le(seek_info->data+60);
|
||||
if (nchan > 1)
|
||||
{
|
||||
buffer[1][-1] = uchar_to_slong_le(seek_info->data+36);
|
||||
buffer[1][-2] = uchar_to_slong_le(seek_info->data+40);
|
||||
buffer[1][-3] = uchar_to_slong_le(seek_info->data+44);
|
||||
offset[1][0] = uchar_to_slong_le(seek_info->data+64);
|
||||
offset[1][1] = uchar_to_slong_le(seek_info->data+68);
|
||||
offset[1][2] = uchar_to_slong_le(seek_info->data+72);
|
||||
offset[1][3] = uchar_to_slong_le(seek_info->data+76);
|
||||
}
|
||||
bitshift = uchar_to_ushort_le(seek_info->data+22);
|
||||
fseek(mFP,(slong)uchar_to_ulong_le(seek_info->data+8),SEEK_SET);
|
||||
fread((uchar*) mDecodeState.getbuf, 1, BUFSIZ, mFP);
|
||||
mDecodeState.getbufp = mDecodeState.getbuf + uchar_to_ushort_le(seek_info->data+14);
|
||||
mDecodeState.nbitget = uchar_to_ushort_le(seek_info->data+16);
|
||||
mDecodeState.nbyteget = uchar_to_ushort_le(seek_info->data+12);
|
||||
mDecodeState.gbuffer = uchar_to_ulong_le(seek_info->data+18);
|
||||
|
||||
mBytesInBuf = 0;
|
||||
|
||||
|
||||
mSeekTo = -1;
|
||||
}
|
||||
|
||||
}
|
||||
chan = (chan + 1) % nchan;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FN_QUIT:
|
||||
/* empty out last of buffer */
|
||||
write_and_wait(mBytesInBuf);
|
||||
|
||||
mEOF = true;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!mGoing)
|
||||
goto finish;
|
||||
if (mSeekTo != -1)
|
||||
{
|
||||
var_get_quit();
|
||||
fwrite_type_quit();
|
||||
|
||||
if (buffer) free((void *) buffer);
|
||||
if (offset) free((void *) offset);
|
||||
if(maxnlpc > 0 && qlpc)
|
||||
free((void *) qlpc);
|
||||
|
||||
fseek(mFP,0,SEEK_SET);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case FN_BLOCKSIZE:
|
||||
blocksize = UINT_GET((int) (log((double) blocksize) / M_LN2));
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
break;
|
||||
case FN_BITSHIFT:
|
||||
bitshift = uvar_get(BITSHIFTSIZE);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
break;
|
||||
case FN_VERBATIM:
|
||||
cklen = uvar_get(VERBATIM_CKSIZE_SIZE);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
|
||||
while (cklen--) {
|
||||
tmp = (uchar)uvar_get(VERBATIM_BYTE_SIZE);
|
||||
if (mFatalError)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
mFatalError = true;
|
||||
//fprintf(stderr,"Sanity check fails trying to decode function: %d\n",cmd);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
write_and_wait(mBytesInBuf);
|
||||
|
||||
finish:
|
||||
|
||||
mSeekTo = -1;
|
||||
mEOF = true;
|
||||
|
||||
/* wind up */
|
||||
var_get_quit();
|
||||
fwrite_type_quit();
|
||||
|
||||
if (buffer) free((void *) buffer);
|
||||
if (offset) free((void *) offset);
|
||||
if(maxnlpc > 0 && qlpc)
|
||||
free((void *) qlpc);
|
||||
|
||||
exit_thread:
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: sulawalaw.c 19 2005-06-07 04:16:15Z vspader $
|
||||
* $Id: sulawalaw.c,v 1.5 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* vario.cpp
|
||||
* shorten_decoder
|
||||
*
|
||||
* Created by Alex Lagutin on Tue Jul 09 2002.
|
||||
* Copyright (c) 2002 Eckysoft All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 1992-1995 Tony Robinson *
|
||||
* *
|
||||
* See the file doc/LICENSE.shorten for conditions on distribution and usage *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: vario.c,v 1.6 2001/12/30 05:12:04 jason Exp $
|
||||
*/
|
||||
|
||||
#include "shn_reader.h"
|
||||
|
||||
void shn_reader::var_get_init()
|
||||
{
|
||||
int i;
|
||||
ulong val = 0;
|
||||
|
||||
masktab[0] = val;
|
||||
for (i = 1; i < MASKTABSIZE; i++)
|
||||
{
|
||||
val <<= 1;
|
||||
val |= 1;
|
||||
masktab[i] = val;
|
||||
}
|
||||
|
||||
mDecodeState.getbuf = (uchar *) malloc(BUFSIZ);
|
||||
mDecodeState.getbufp = mDecodeState.getbuf;
|
||||
mDecodeState.nbyteget = 0;
|
||||
mDecodeState.gbuffer = 0;
|
||||
mDecodeState.nbitget = 0;
|
||||
|
||||
if (!mDecodeState.getbuf)
|
||||
mFatalError = true;
|
||||
}
|
||||
|
||||
ulong shn_reader::word_get()
|
||||
{
|
||||
ulong buffer;
|
||||
|
||||
if (mDecodeState.nbyteget < 4)
|
||||
{
|
||||
mDecodeState.nbyteget += fread(mDecodeState.getbuf, 1, BUFSIZ, mFP);
|
||||
if (mDecodeState.nbyteget < 4)
|
||||
{
|
||||
mFatalError = true;
|
||||
return 0;
|
||||
}
|
||||
mDecodeState.getbufp = mDecodeState.getbuf;
|
||||
}
|
||||
|
||||
buffer = (((long) (mDecodeState.getbufp[0])) << 24) | (((long) (mDecodeState.getbufp[1])) << 16)
|
||||
| (((long) (mDecodeState.getbufp[2])) << 8) | ((long) (mDecodeState.getbufp[3]));
|
||||
|
||||
mDecodeState.getbufp += 4;
|
||||
mDecodeState.nbyteget -= 4;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
long shn_reader::uvar_get(int nbin)
|
||||
{
|
||||
long result;
|
||||
|
||||
if (!mDecodeState.nbitget)
|
||||
{
|
||||
mDecodeState.gbuffer = word_get();
|
||||
if (mFatalError)
|
||||
return 0;
|
||||
mDecodeState.nbitget = 32;
|
||||
}
|
||||
|
||||
for (result = 0; !(mDecodeState.gbuffer & (1L << --(mDecodeState.nbitget))); result++)
|
||||
{
|
||||
if (!mDecodeState.nbitget)
|
||||
{
|
||||
mDecodeState.gbuffer = word_get();
|
||||
if (mFatalError)
|
||||
return 0;
|
||||
mDecodeState.nbitget = 32;
|
||||
}
|
||||
}
|
||||
|
||||
while (nbin)
|
||||
{
|
||||
if(mDecodeState.nbitget >= nbin)
|
||||
{
|
||||
result = (result << nbin) | ((mDecodeState.gbuffer >> (mDecodeState.nbitget-nbin)) & masktab[nbin]);
|
||||
mDecodeState.nbitget -= nbin;
|
||||
nbin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (result << mDecodeState.nbitget) | (mDecodeState.gbuffer & masktab[mDecodeState.nbitget]);
|
||||
mDecodeState.gbuffer = word_get();
|
||||
if (mFatalError)
|
||||
return 0;
|
||||
nbin -= mDecodeState.nbitget;
|
||||
mDecodeState.nbitget = 32;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ulong shn_reader::ulong_get()
|
||||
{
|
||||
uint nbit = uvar_get(ULONGSIZE);
|
||||
|
||||
if (mFatalError)
|
||||
return 0;
|
||||
|
||||
return uvar_get(nbit);
|
||||
}
|
||||
|
||||
long shn_reader::var_get(int nbin)
|
||||
{
|
||||
ulong uvar = uvar_get(nbin + 1);
|
||||
if (mFatalError)
|
||||
return 0;
|
||||
|
||||
return ((uvar & 1) ? ((long) ~(uvar >> 1)) : ((long) (uvar >> 1)));
|
||||
}
|
||||
|
||||
void shn_reader::var_get_quit()
|
||||
{
|
||||
free(mDecodeState.getbuf);
|
||||
mDecodeState.getbuf = NULL;
|
||||
}
|
|
@ -7,62 +7,54 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
597A37500A2A2C9A00730CFA /* bitshift.h in Headers */ = {isa = PBXBuildFile; fileRef = 59FDCD5D0A29226D006C1800 /* bitshift.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
597A37510A2A2C9A00730CFA /* ringbuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59FDCD5E0A29226D006C1800 /* ringbuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
597A37520A2A2C9A00730CFA /* shn_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 59FDCD5F0A29226D006C1800 /* shn_reader.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
597A37530A2A2C9A00730CFA /* shorten.h in Headers */ = {isa = PBXBuildFile; fileRef = 59FDCD600A29226D006C1800 /* shorten.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
59F1214E0A311CD40052FE42 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 59F1214D0A311CD40052FE42 /* config.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
59FDCD6C0A2922E1006C1800 /* array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD650A2922E1006C1800 /* array.cpp */; };
|
||||
59FDCD6D0A2922E1006C1800 /* fixio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD660A2922E1006C1800 /* fixio.cpp */; };
|
||||
59FDCD6E0A2922E1006C1800 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD670A2922E1006C1800 /* ringbuffer.cpp */; };
|
||||
59FDCD6F0A2922E1006C1800 /* seek.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD680A2922E1006C1800 /* seek.cpp */; };
|
||||
59FDCD700A2922E1006C1800 /* shn_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD690A2922E1006C1800 /* shn_reader.cpp */; };
|
||||
59FDCD710A2922E1006C1800 /* sulawalaw.c in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD6A0A2922E1006C1800 /* sulawalaw.c */; };
|
||||
59FDCD720A2922E1006C1800 /* vario.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59FDCD6B0A2922E1006C1800 /* vario.cpp */; };
|
||||
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
||||
8E756C7109F3174E0080F1EE /* bitshift.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E756C6C09F3174E0080F1EE /* bitshift.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8E756C7209F3174E0080F1EE /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E756C6D09F3174E0080F1EE /* config.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8E756C7309F3174E0080F1EE /* decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E756C6E09F3174E0080F1EE /* decode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8E756C7409F3174E0080F1EE /* shn.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E756C6F09F3174E0080F1EE /* shn.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8E756C7509F3174E0080F1EE /* shorten.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E756C7009F3174E0080F1EE /* shorten.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8E756C8609F317680080F1EE /* array.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C7A09F317680080F1EE /* array.c */; };
|
||||
8E756C8709F317680080F1EE /* convert.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C7B09F317680080F1EE /* convert.c */; };
|
||||
8E756C8809F317680080F1EE /* decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C7C09F317680080F1EE /* decode.c */; };
|
||||
8E756C8909F317680080F1EE /* fixio.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C7D09F317680080F1EE /* fixio.c */; };
|
||||
8E756C8A09F317680080F1EE /* id3v2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C7E09F317680080F1EE /* id3v2.c */; };
|
||||
8E756C8B09F317680080F1EE /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C7F09F317680080F1EE /* misc.c */; };
|
||||
8E756C8C09F317680080F1EE /* output.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C8009F317680080F1EE /* output.c */; };
|
||||
8E756C8D09F317680080F1EE /* seek.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C8109F317680080F1EE /* seek.c */; };
|
||||
8E756C8E09F317680080F1EE /* shorten.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C8209F317680080F1EE /* shorten.c */; };
|
||||
8E756C8F09F317680080F1EE /* sulawalaw.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C8309F317680080F1EE /* sulawalaw.c */; };
|
||||
8E756C9009F317680080F1EE /* vario.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C8409F317680080F1EE /* vario.c */; };
|
||||
8E756C9109F317680080F1EE /* wave.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E756C8509F317680080F1EE /* wave.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXBuildStyle section */
|
||||
014CEA440018CDF011CA2923 /* Debug */ = {
|
||||
8E8303D10A3226D3008E1F34 /* Development */ = {
|
||||
isa = PBXBuildStyle;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
};
|
||||
name = Debug;
|
||||
name = Development;
|
||||
};
|
||||
014CEA450018CDF011CA2923 /* Release */ = {
|
||||
8E8303D20A3226D3008E1F34 /* Deployment */ = {
|
||||
isa = PBXBuildStyle;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
};
|
||||
name = Release;
|
||||
name = Deployment;
|
||||
};
|
||||
/* End PBXBuildStyle section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
59F1214D0A311CD40052FE42 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = config.h; path = Files/shorten/include/config.h; sourceTree = "<group>"; };
|
||||
59FDCD5D0A29226D006C1800 /* bitshift.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = bitshift.h; path = Files/shorten/include/bitshift.h; sourceTree = "<group>"; };
|
||||
59FDCD5E0A29226D006C1800 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ringbuffer.h; path = Files/shorten/include/ringbuffer.h; sourceTree = "<group>"; };
|
||||
59FDCD5F0A29226D006C1800 /* shn_reader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = shn_reader.h; path = Files/shorten/include/shn_reader.h; sourceTree = "<group>"; };
|
||||
59FDCD600A29226D006C1800 /* shorten.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = shorten.h; path = Files/shorten/include/shorten.h; sourceTree = "<group>"; };
|
||||
59FDCD650A2922E1006C1800 /* array.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = array.cpp; path = Files/shorten/src/array.cpp; sourceTree = "<group>"; };
|
||||
59FDCD660A2922E1006C1800 /* fixio.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fixio.cpp; path = Files/shorten/src/fixio.cpp; sourceTree = "<group>"; };
|
||||
59FDCD670A2922E1006C1800 /* ringbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ringbuffer.cpp; path = Files/shorten/src/ringbuffer.cpp; sourceTree = "<group>"; };
|
||||
59FDCD680A2922E1006C1800 /* seek.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = seek.cpp; path = Files/shorten/src/seek.cpp; sourceTree = "<group>"; };
|
||||
59FDCD690A2922E1006C1800 /* shn_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = shn_reader.cpp; path = Files/shorten/src/shn_reader.cpp; sourceTree = "<group>"; };
|
||||
59FDCD6A0A2922E1006C1800 /* sulawalaw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sulawalaw.c; path = Files/shorten/src/sulawalaw.c; sourceTree = "<group>"; };
|
||||
59FDCD6B0A2922E1006C1800 /* vario.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = vario.cpp; path = Files/shorten/src/vario.cpp; sourceTree = "<group>"; };
|
||||
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
8DC2EF5B0486A6940098B216 /* Shorten.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Shorten.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8E756C6C09F3174E0080F1EE /* bitshift.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = bitshift.h; path = Files/shorten/include/bitshift.h; sourceTree = "<group>"; };
|
||||
8E756C6D09F3174E0080F1EE /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = config.h; path = Files/shorten/include/config.h; sourceTree = "<group>"; };
|
||||
8E756C6E09F3174E0080F1EE /* decode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = decode.h; path = Files/shorten/include/decode.h; sourceTree = "<group>"; };
|
||||
8E756C6F09F3174E0080F1EE /* shn.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = shn.h; path = Files/shorten/include/shn.h; sourceTree = "<group>"; };
|
||||
8E756C7009F3174E0080F1EE /* shorten.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = shorten.h; path = Files/shorten/include/shorten.h; sourceTree = "<group>"; };
|
||||
8E756C7A09F317680080F1EE /* array.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = array.c; path = Files/shorten/src/array.c; sourceTree = "<group>"; };
|
||||
8E756C7B09F317680080F1EE /* convert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = convert.c; path = Files/shorten/src/convert.c; sourceTree = "<group>"; };
|
||||
8E756C7C09F317680080F1EE /* decode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = decode.c; path = Files/shorten/src/decode.c; sourceTree = "<group>"; };
|
||||
8E756C7D09F317680080F1EE /* fixio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fixio.c; path = Files/shorten/src/fixio.c; sourceTree = "<group>"; };
|
||||
8E756C7E09F317680080F1EE /* id3v2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = id3v2.c; path = Files/shorten/src/id3v2.c; sourceTree = "<group>"; };
|
||||
8E756C7F09F317680080F1EE /* misc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = misc.c; path = Files/shorten/src/misc.c; sourceTree = "<group>"; };
|
||||
8E756C8009F317680080F1EE /* output.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = output.c; path = Files/shorten/src/output.c; sourceTree = "<group>"; };
|
||||
8E756C8109F317680080F1EE /* seek.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = seek.c; path = Files/shorten/src/seek.c; sourceTree = "<group>"; };
|
||||
8E756C8209F317680080F1EE /* shorten.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = shorten.c; path = Files/shorten/src/shorten.c; sourceTree = "<group>"; };
|
||||
8E756C8309F317680080F1EE /* sulawalaw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sulawalaw.c; path = Files/shorten/src/sulawalaw.c; sourceTree = "<group>"; };
|
||||
8E756C8409F317680080F1EE /* vario.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = vario.c; path = Files/shorten/src/vario.c; sourceTree = "<group>"; };
|
||||
8E756C8509F317680080F1EE /* wave.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = wave.c; path = Files/shorten/src/wave.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -131,18 +123,13 @@
|
|||
8E756C6A09F317170080F1EE /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E756C7A09F317680080F1EE /* array.c */,
|
||||
8E756C7B09F317680080F1EE /* convert.c */,
|
||||
8E756C7C09F317680080F1EE /* decode.c */,
|
||||
8E756C7D09F317680080F1EE /* fixio.c */,
|
||||
8E756C7E09F317680080F1EE /* id3v2.c */,
|
||||
8E756C7F09F317680080F1EE /* misc.c */,
|
||||
8E756C8009F317680080F1EE /* output.c */,
|
||||
8E756C8109F317680080F1EE /* seek.c */,
|
||||
8E756C8209F317680080F1EE /* shorten.c */,
|
||||
8E756C8309F317680080F1EE /* sulawalaw.c */,
|
||||
8E756C8409F317680080F1EE /* vario.c */,
|
||||
8E756C8509F317680080F1EE /* wave.c */,
|
||||
59FDCD650A2922E1006C1800 /* array.cpp */,
|
||||
59FDCD660A2922E1006C1800 /* fixio.cpp */,
|
||||
59FDCD670A2922E1006C1800 /* ringbuffer.cpp */,
|
||||
59FDCD680A2922E1006C1800 /* seek.cpp */,
|
||||
59FDCD690A2922E1006C1800 /* shn_reader.cpp */,
|
||||
59FDCD6A0A2922E1006C1800 /* sulawalaw.c */,
|
||||
59FDCD6B0A2922E1006C1800 /* vario.cpp */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
|
@ -150,11 +137,11 @@
|
|||
8E756C6B09F3171C0080F1EE /* Headers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E756C6C09F3174E0080F1EE /* bitshift.h */,
|
||||
8E756C6D09F3174E0080F1EE /* config.h */,
|
||||
8E756C6E09F3174E0080F1EE /* decode.h */,
|
||||
8E756C6F09F3174E0080F1EE /* shn.h */,
|
||||
8E756C7009F3174E0080F1EE /* shorten.h */,
|
||||
59F1214D0A311CD40052FE42 /* config.h */,
|
||||
59FDCD5D0A29226D006C1800 /* bitshift.h */,
|
||||
59FDCD5E0A29226D006C1800 /* ringbuffer.h */,
|
||||
59FDCD5F0A29226D006C1800 /* shn_reader.h */,
|
||||
59FDCD600A29226D006C1800 /* shorten.h */,
|
||||
);
|
||||
name = Headers;
|
||||
sourceTree = "<group>";
|
||||
|
@ -162,15 +149,15 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
8DC2EF500486A6940098B216 /* Headers */ = {
|
||||
597A374E0A2A2C5300730CFA /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8E756C7109F3174E0080F1EE /* bitshift.h in Headers */,
|
||||
8E756C7209F3174E0080F1EE /* config.h in Headers */,
|
||||
8E756C7309F3174E0080F1EE /* decode.h in Headers */,
|
||||
8E756C7409F3174E0080F1EE /* shn.h in Headers */,
|
||||
8E756C7509F3174E0080F1EE /* shorten.h in Headers */,
|
||||
597A37500A2A2C9A00730CFA /* bitshift.h in Headers */,
|
||||
597A37510A2A2C9A00730CFA /* ringbuffer.h in Headers */,
|
||||
597A37520A2A2C9A00730CFA /* shn_reader.h in Headers */,
|
||||
597A37530A2A2C9A00730CFA /* shorten.h in Headers */,
|
||||
59F1214E0A311CD40052FE42 /* config.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -181,15 +168,13 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Shorten" */;
|
||||
buildPhases = (
|
||||
8DC2EF500486A6940098B216 /* Headers */,
|
||||
597A374E0A2A2C5300730CFA /* Headers */,
|
||||
8DC2EF520486A6940098B216 /* Resources */,
|
||||
8DC2EF540486A6940098B216 /* Sources */,
|
||||
8DC2EF560486A6940098B216 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
buildSettings = {
|
||||
};
|
||||
dependencies = (
|
||||
);
|
||||
name = Shorten;
|
||||
|
@ -207,8 +192,8 @@
|
|||
buildSettings = {
|
||||
};
|
||||
buildStyles = (
|
||||
014CEA440018CDF011CA2923 /* Debug */,
|
||||
014CEA450018CDF011CA2923 /* Release */,
|
||||
8E8303D10A3226D3008E1F34 /* Development */,
|
||||
8E8303D20A3226D3008E1F34 /* Deployment */,
|
||||
);
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 0867D691FE84028FC02AAC07 /* Shorten */;
|
||||
|
@ -236,18 +221,13 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8E756C8609F317680080F1EE /* array.c in Sources */,
|
||||
8E756C8709F317680080F1EE /* convert.c in Sources */,
|
||||
8E756C8809F317680080F1EE /* decode.c in Sources */,
|
||||
8E756C8909F317680080F1EE /* fixio.c in Sources */,
|
||||
8E756C8A09F317680080F1EE /* id3v2.c in Sources */,
|
||||
8E756C8B09F317680080F1EE /* misc.c in Sources */,
|
||||
8E756C8C09F317680080F1EE /* output.c in Sources */,
|
||||
8E756C8D09F317680080F1EE /* seek.c in Sources */,
|
||||
8E756C8E09F317680080F1EE /* shorten.c in Sources */,
|
||||
8E756C8F09F317680080F1EE /* sulawalaw.c in Sources */,
|
||||
8E756C9009F317680080F1EE /* vario.c in Sources */,
|
||||
8E756C9109F317680080F1EE /* wave.c in Sources */,
|
||||
59FDCD6C0A2922E1006C1800 /* array.cpp in Sources */,
|
||||
59FDCD6D0A2922E1006C1800 /* fixio.cpp in Sources */,
|
||||
59FDCD6E0A2922E1006C1800 /* ringbuffer.cpp in Sources */,
|
||||
59FDCD6F0A2922E1006C1800 /* seek.cpp in Sources */,
|
||||
59FDCD700A2922E1006C1800 /* shn_reader.cpp in Sources */,
|
||||
59FDCD710A2922E1006C1800 /* sulawalaw.c in Sources */,
|
||||
59FDCD720A2922E1006C1800 /* vario.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -315,6 +295,12 @@
|
|||
buildSettings = {
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
.,
|
||||
../include,
|
||||
../../include,
|
||||
include,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
|
@ -325,6 +311,12 @@
|
|||
buildSettings = {
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
.,
|
||||
../include,
|
||||
../../include,
|
||||
include,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Shorten/shn_reader.h>
|
||||
|
||||
#import "SoundFile.h"
|
||||
|
||||
#import "Shorten/shorten.h"
|
||||
#import "Shorten/shn.h"
|
||||
#import "Shorten/decode.h"
|
||||
|
||||
@interface ShnFile : SoundFile {
|
||||
shn_file *handle;
|
||||
//shn_file *handle;
|
||||
shn_reader *decoder;
|
||||
|
||||
int bufferSize; //total size
|
||||
long bufferSize; //total size
|
||||
void *buffer;
|
||||
int bufferAmount; //amount currently in
|
||||
void *inputBuffer;//derek
|
||||
long bufferAmount; //amount currently in
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
//
|
||||
// ShnFile.m
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/6/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "ShnFile.h"
|
||||
|
||||
|
||||
@implementation ShnFile
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
if ([self readInfo:filename] == NO)
|
||||
return NO;
|
||||
|
||||
bufferSize = shn_get_buffer_block_size(handle, 512);
|
||||
buffer = malloc(bufferSize);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
shn_config conf;
|
||||
int r;
|
||||
|
||||
conf.error_output_method = ERROR_OUTPUT_DEVNULL;
|
||||
conf.seek_tables_path = NULL;
|
||||
conf.relative_seek_tables_path = ".";
|
||||
conf.verbose = 0;
|
||||
conf.swap_bytes = 0;
|
||||
|
||||
handle = shn_load((char *)filename, conf);
|
||||
if (!handle)
|
||||
return NO;
|
||||
|
||||
r = shn_init_decoder(handle);
|
||||
if (r < 0)
|
||||
return NO;
|
||||
|
||||
channels = shn_get_channels(handle);
|
||||
frequency = shn_get_samplerate(handle);
|
||||
bitsPerSample = shn_get_bitspersample(handle);
|
||||
|
||||
unsigned int length;
|
||||
length = shn_get_song_length(handle);
|
||||
totalSize = (((double)(length)*frequency)/1000.0) * channels * (bitsPerSample/8);
|
||||
|
||||
bitRate = (int)((double)totalSize/((double)length/1000.0));
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int numread = bufferAmount;
|
||||
int count = 0;
|
||||
|
||||
//Fill from buffer, going by bufferAmount
|
||||
//if still needs more, decode and repeat
|
||||
if (bufferAmount == 0)
|
||||
{
|
||||
bufferAmount = shn_read(handle, buffer, bufferSize);
|
||||
if (bufferAmount == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = bufferAmount;
|
||||
if (bufferAmount > size)
|
||||
{
|
||||
count = size;
|
||||
}
|
||||
|
||||
memcpy(buf, buffer, count);
|
||||
|
||||
bufferAmount -= count;
|
||||
|
||||
if (bufferAmount > 0)
|
||||
memmove(buffer, &buffer[count], bufferAmount);
|
||||
|
||||
if (count < size)
|
||||
numread = [self fillBuffer:(&((char *)buf)[count]) ofSize:(size - count)];
|
||||
else
|
||||
numread = 0;
|
||||
|
||||
return count + numread;
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
unsigned int sec;
|
||||
|
||||
if (!shn_seekable(handle))
|
||||
return -1.0;
|
||||
|
||||
sec = (int)(milliseconds/1000.0);
|
||||
|
||||
shn_seek(handle, sec);
|
||||
|
||||
return (sec * 1000.0);
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
|
||||
if (shn_cleanup_decoder(handle))
|
||||
shn_unload(handle);
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue