Skip to content

Commit

Permalink
Merge pull request #1 from Sergeanur/master
Browse files Browse the repository at this point in the history
Stream playback implemented
  • Loading branch information
CookiePLMonster authored Jan 28, 2017
2 parents 59d16a7 + 56387eb commit 0f89b51
Show file tree
Hide file tree
Showing 2 changed files with 272 additions and 47 deletions.
233 changes: 199 additions & 34 deletions vbdec.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "vbdec.h"

#define GET_BLOCK(offset) ( offset >> 13 )


static HPROVIDER providerHandle;
void RegisterVBInterface()
Expand All @@ -9,22 +11,43 @@ void RegisterVBInterface()
REG_FN(PROVIDER_query_attribute),
REG_AT("Name", PROVIDER_NAME, RIB_STRING),
REG_AT("Version", PROVIDER_VERSION, RIB_HEX),
REG_AT("Input file types", PROVIDER_InputFileTypes, RIB_STRING),
REG_AT("Input wave tag", PROVIDER_InputWaveTag, RIB_DEC),
REG_AT("Output file types", PROVIDER_OutputFileTypes, RIB_STRING),
REG_AT("Maximum frame size", PROVIDER_MaxFrameSize, RIB_DEC),
REG_AT("Input file types", IN_FTYPES, RIB_STRING),
//REG_AT("Input wave tag", IN_WTAG, RIB_DEC),
REG_AT("Output file types", OUT_FTYPES, RIB_STRING),
REG_AT("Maximum frame size", FRAME_SIZE, RIB_DEC),
REG_FN(ASI_startup),
REG_FN(ASI_error),
REG_FN(ASI_shutdown),
};

// ASI stream
const RIB_INTERFACE_ENTRY streamEntries[] = {
REG_FN(ASI_stream_open),
REG_FN(ASI_stream_process),
REG_FN(ASI_stream_attribute),
REG_FN(ASI_stream_set_preference),
REG_FN(ASI_stream_seek),
REG_FN( ASI_stream_open ),
REG_FN( ASI_stream_process ),
REG_FN( ASI_stream_attribute ),
REG_FN( ASI_stream_set_preference ),
REG_FN( ASI_stream_seek ),
REG_FN( ASI_stream_close ),
REG_AT("Input bit rate", INPUT_BIT_RATE, RIB_DEC),
REG_AT("Input sample rate", INPUT_SAMPLE_RATE, RIB_DEC),
REG_AT("Input sample width", INPUT_BITS, RIB_DEC),
REG_AT("Input channels", INPUT_CHANNELS, RIB_DEC),
REG_AT("Output bit rate", OUTPUT_BIT_RATE, RIB_DEC),
REG_AT("Output sample rate", OUTPUT_SAMPLE_RATE, RIB_DEC),
REG_AT("Output sample width", OUTPUT_BITS, RIB_DEC),
REG_AT("Output channels", OUTPUT_CHANNELS, RIB_DEC),
REG_AT("Position", POSITION, RIB_DEC),
REG_AT("Percent done", PERCENT_DONE, RIB_PERCENT),
REG_AT("Minimum input block size", MIN_INPUT_BLOCK_SIZE, RIB_DEC),
//REG_AT("MPEG version", MPEG_VERSION, RIB_DEC),
//REG_AT("MPEG layer", MPEG_LAYER, RIB_DEC),
//REG_AT("Interleave", INTERLEAVE, RIB_DEC),
//REG_PR("Raw source sample rate", RAW_RATE, RIB_DEC),
//REG_PR("Raw source sample width", RAW_BITS, RIB_DEC),
//REG_PR("Raw source channels", RAW_CHANNELS, RIB_DEC),
REG_PR("Requested sample rate", REQUESTED_RATE, RIB_DEC),
REG_PR("Requested sample width", REQUESTED_BITS, RIB_DEC),
REG_PR("Requested channels", REQUESTED_CHANS, RIB_DEC)
};

providerHandle = RIB_provider_library_handle();
Expand All @@ -47,14 +70,14 @@ U32 AILCALL FAR PROVIDER_query_attribute(HATTRIB index)
return (U32)"MSS VB Audio Decoder";
case PROVIDER_VERSION:
return 0x100;
case PROVIDER_InputFileTypes:
case IN_FTYPES: // Input file types
return (U32)"VB audio files\0*.VB";
case PROVIDER_InputWaveTag:
return 85;
case PROVIDER_OutputFileTypes:
//case IN_WTAG: // Input wave tag
// return 85;
case OUT_FTYPES: // Output file types;
return (U32)"Raw PCM files\0*.RAW";
case PROVIDER_MaxFrameSize:
return 0x1000;
case FRAME_SIZE: // Maximum frame size
return 0x4000;
default:
return 0;
}
Expand Down Expand Up @@ -89,40 +112,182 @@ C8 FAR* AILCALL FAR ASI_error(void)

// ASI stream

HASISTREAM AILCALL FAR ASI_stream_open(U32 user, AILASIFETCHCB fetch_CB, U32 total_size)
bool tfile = false;
void FetchStr( ASISTREAM *STR, int offset = -1 )
{
void* stream = AIL_mem_alloc_lock( 4 );
return (HASISTREAM)stream;
}
for (int i = 0; i < 2; i++)
{
STR->fetch_CB(STR->user, STR->channels[i].block_buffer, 0x2000, offset);
if (offset != -1)
{
STR->channels[i].s_1 = 0.0;
STR->channels[i].s_2 = 0.0;
}
}

S32 AILCALL FAR ASI_stream_process(HASISTREAM stream, void FAR *buffer, S32 buffer_size)
{
double f[5][2] = { { 0.0, 0.0 },
{ 60.0 / 64.0, 0.0 },
{ 115.0 / 64.0, -52.0 / 64.0 },
{ 98.0 / 64.0, -55.0 / 64.0 },
{ 122.0 / 64.0, -60.0 / 64.0 } };

return 0;
U8 *bufs[] = { STR->channels[0].block_buffer, STR->channels[1].block_buffer };
S16 *dest[] = { STR->channels[0].frame, STR->channels[1].frame };
for (int c = 0; c < 2; c++)
{
for ( int a = 0; a < 0x7000; a+=(28 * 2))
{
//if (buffer_size <= 0) break;
int predict_nr = *(bufs[c]++);
int shift_factor = predict_nr & 0xf;
predict_nr >>= 4;
int flags = *(bufs[c]++);
if ( flags == 7 ) break;
for ( int i = 0; i < 28; i += 2 )
{
int d = *(bufs[c]++);
int s = ( d & 0xf ) << 12;
if ( s & 0x8000 )
s |= 0xffff0000;
STR->channels[c].samples[i] = (double) ( s >> shift_factor );
s = ( d & 0xf0 ) << 8;
if ( s & 0x8000 )
s |= 0xffff0000;
STR->channels[c].samples[i+1] = (double) ( s >> shift_factor );

}
for ( int i = 0; i < 28; i++ )
{
STR->channels[c].samples[i] = STR->channels[c].samples[i] + STR->channels[c].s_1 * f[predict_nr][0] + STR->channels[c].s_2 * f[predict_nr][1];
STR->channels[c].s_2 = STR->channels[c].s_1;
STR->channels[c].s_1 = STR->channels[c].samples[i];
int d = (int) ( STR->channels[c].samples[i] + 0.5 );
*(dest[c]++) = (d & 0xffff);
}
if ( flags == 1 ) break;
}
}
}

S32 AILCALL FAR ASI_stream_attribute(HASISTREAM stream, HATTRIB attrib)
HASISTREAM AILCALL FAR ASI_stream_open(U32 user, AILASIFETCHCB fetch_CB, U32 total_size)
{
ASISTREAM FAR *STR = (ASISTREAM FAR *) AIL_mem_alloc_lock((sizeof(ASISTREAM) + 15) & ~15);
if (STR == NULL)
{
//strcpy(ASI_error_text,"Out of memory");
return 0;
}

memset(STR, 0, sizeof(ASISTREAM));

return -1;
}
STR->user = user;
STR->fetch_CB = fetch_CB;
STR->size = total_size;

S32 AILCALL FAR ASI_stream_set_preference(HASISTREAM stream, HATTRIB preference, void FAR* value)
{
STR->cursor = 0;
STR->offset = 0;
STR->cur_block = -1;
STR->blocks = total_size / 0x4000;

return -1;
for (int i = 0; i < 2; i++)
{
STR->channels[i].s_1 = 0.0;
STR->channels[i].s_2 = 0.0;
memset(STR->channels[i].samples, 0, 28 * sizeof(double));
memset(STR->channels[i].block_buffer, 0, 0x2000);
memset(STR->channels[i].frame, 0, 0x3800);
}

return (HASISTREAM)STR;
}

ASIRESULT AILCALL ASI_stream_close(HASISTREAM stream)
{
ASISTREAM FAR *STR = (ASISTREAM FAR *) stream;

AIL_mem_free_lock(STR);

return ASI_NOERR;
}

ASIRESULT AILCALL FAR ASI_stream_seek(HASISTREAM stream, S32 stream_offset)
S32 AILCALL FAR ASI_stream_process(HASISTREAM stream, void FAR *buffer, S32 buffer_size)
{
S32 tbuffer_size = buffer_size;

ASISTREAM *STR = (ASISTREAM*)stream;

if (GET_BLOCK(STR->offset) != STR->cur_block)
{
FetchStr(STR);
STR->cur_block = GET_BLOCK(STR->offset);
}


S16 *dest = (S16 *)buffer;

for (int i = 0; i < buffer_size / 2; i++)
{
for (int c = 0; c < 2; c++)
dest[i * 2 + c] = STR->channels[c].frame[STR->cursor + i];
}
STR->cursor += buffer_size / 4;
if (STR->cursor >= 0x3800)
{
STR->cursor = 0;
STR->offset += 0x2000;
}

return ASI_NOERR;
return buffer_size;
}

ASIRESULT AILCALL FAR ASI_stream_close(HASISTREAM stream)
bool sfile = false;
ASIRESULT AILCALL ASI_stream_seek (HASISTREAM stream, S32 stream_offset)
{

ASISTREAM *STR = (ASISTREAM*)stream;
if (stream_offset > STR->size) return ASI_INVALID_PARAM;

if (stream_offset != -2) // loop
stream_offset = 0;

stream_offset &= 0xFFFFE000;
STR->offset = stream_offset;

if (GET_BLOCK(STR->offset) != STR->cur_block)
{
FetchStr(STR, STR->offset);
STR->cur_block = GET_BLOCK(STR->offset);
}
STR->cursor = 0;

return ASI_NOERR;
}

S32 AILCALL FAR ASI_stream_attribute (HASISTREAM stream, HATTRIB attrib)
{
void* mem = (void*)stream;
AIL_mem_free_lock( mem );
ASISTREAM *STR = (ASISTREAM*)stream;
switch (attrib)
{
case INPUT_BIT_RATE: return 0x7D00000;
case INPUT_SAMPLE_RATE: return 1000;
case INPUT_BITS: return 128;
case INPUT_CHANNELS: return 2;
case OUTPUT_BIT_RATE: return 32000 * 16 * 2;
case OUTPUT_SAMPLE_RATE: return 32000;
case OUTPUT_BITS: return 16;
case OUTPUT_CHANNELS: return 2;
case POSITION: return STR->offset;
case PERCENT_DONE:
{
float percent = ((float)(100.0 * STR->offset) / (STR->size / 0x4000));
return *(S32*)&percent;
}
case MIN_INPUT_BLOCK_SIZE: return 0x4000;
}
return -1;
}

return ASI_NOERR;
S32 AILCALL FAR ASI_stream_set_preference (HASISTREAM stream, HATTRIB preference, void FAR* value)
{
return 0;
}
86 changes: 73 additions & 13 deletions vbdec.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,74 @@
#pragma once

#include "mss/mss.h"
#include <iostream>

enum PROPERTY
{
//
// Additional decoder props (beyond standard RIB PROVIDER_ properties)
//

IN_FTYPES, // STRING supported input file types
IN_WTAG, // Tag used for this data in a wave file
OUT_FTYPES, // STRING supported output file types
FRAME_SIZE, // S32 worst-case frame buffer size

INPUT_BIT_RATE, // S32 input bit rate
INPUT_SAMPLE_RATE, // S32 sample rate of input data
INPUT_BITS, // S32 bit width per sample of input data
INPUT_CHANNELS, // S32 # of channels in input data

OUTPUT_BIT_RATE, // S32 output bit rate
OUTPUT_SAMPLE_RATE, // S32 output sample rate
OUTPUT_BITS, // S32 bit width per sample of output data
OUTPUT_CHANNELS, // S32 # of channels in output data

POSITION, // S32 bytes processed so far
PERCENT_DONE, // % percent done
MIN_INPUT_BLOCK_SIZE, // S32 minimum block size for input

//
// Codec-specific stream props
//
//INTERLEAVE,

//
// Stream properties
//

//RAW_RATE,
//RAW_BITS,
//RAW_CHANNELS,

REQUESTED_RATE, // S32 requested rate for output data
REQUESTED_BITS, // S32 requested bit width for output data
REQUESTED_CHANS // S32 requested # of channels for output data
};

struct ASISTREAM
{
U32 user;
U32 size;
AILASIFETCHCB fetch_CB;

U32 offset;

U32 cursor;
U32 blocks;
U32 cur_block;

//U32 block_buffer[2][0x1000];
struct
{
double s_1, s_2;
double samples[28];
U8 block_buffer[0x2000];
S16 frame[0x3800];
} channels[2];

//FILE* debug_file;
};

void RegisterVBInterface();
void UnregisterVBInterface();
Expand All @@ -11,16 +79,8 @@ ASIRESULT AILCALL FAR ASI_shutdown(void);
C8 FAR* AILCALL FAR ASI_error(void);

HASISTREAM AILCALL FAR ASI_stream_open(U32 user, AILASIFETCHCB fetch_CB, U32 total_size);
S32 AILCALL FAR ASI_stream_process(HASISTREAM stream, void FAR *buffer, S32 buffer_size);
S32 AILCALL FAR ASI_stream_attribute(HASISTREAM stream, HATTRIB attrib);
S32 AILCALL FAR ASI_stream_set_preference(HASISTREAM stream, HATTRIB preference, void FAR* value);
ASIRESULT AILCALL FAR ASI_stream_seek(HASISTREAM stream, S32 stream_offset);
ASIRESULT AILCALL FAR ASI_stream_close(HASISTREAM stream);

enum VBAttrib
{
PROVIDER_InputFileTypes,
PROVIDER_InputWaveTag,
PROVIDER_OutputFileTypes,
PROVIDER_MaxFrameSize,
};
ASIRESULT AILCALL ASI_stream_close(HASISTREAM stream);
ASIRESULT AILCALL ASI_stream_seek (HASISTREAM stream, S32 stream_offset);
S32 AILCALL FAR ASI_stream_process(HASISTREAM stream, void FAR *buffer, S32 buffer_size);
S32 AILCALL FAR ASI_stream_attribute (HASISTREAM stream, HATTRIB attrib);
S32 AILCALL FAR ASI_stream_set_preference (HASISTREAM stream, HATTRIB preference, void FAR* value);

0 comments on commit 0f89b51

Please sign in to comment.