13
0
livetrax/libs/ptformat/ptfformat.cc
Damien Zammit 277893b130 ptformat: Make PT import more resilient to bad user choices and display messages
Previously, libptformat would attempt to parse all kinds of files,
now the library stops parsing when the version number and session rate
is outside valid ranges, returning an error code to the caller.

If there is a valid PT file detected, but some audio files are missing,
Ardour now pops up an error message to inform the user that some files
may be missing from the import.  A success message is displayed otherwise.

Signed-off-by: Damien Zammit <damien@zamaudio.com>
2016-04-16 12:21:12 +02:00

1344 lines
28 KiB
C++

/*
Copyright (C) 2015 Damien Zammit
Copyright (C) 2015 Robin Gareus
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 3 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.
*/
#include "ptfformat.h"
#include <stdio.h>
#include <string>
#include <string.h>
#include <assert.h>
using namespace std;
static const uint32_t baselut[16] = {
0xaaaaaaaa, 0xaa955555, 0xa9554aaa, 0xa552a955,
0xb56ad5aa, 0x95a95a95, 0x94a5294a, 0x9696b4b5,
0xd2d25a5a, 0xd24b6d25, 0xdb6db6da, 0xd9249b6d,
0xc9b64d92, 0xcd93264d, 0xccd99b32, 0xcccccccd
};
static const uint32_t xorlut[16] = {
0x00000000, 0x00000b00, 0x000100b0, 0x00b0b010,
0x010b0b01, 0x0b10b10b, 0x01bb101b, 0x0111bbbb,
0x1111bbbb, 0x1bbb10bb, 0x1bb0bb0b, 0xbb0b0bab,
0xbab0b0ba, 0xb0abaaba, 0xba0aabaa, 0xbaaaaaaa
};
static uint32_t swapbytes32 (const uint32_t v) {
uint32_t rv = 0;
rv |= ((v >> 0) & 0xf) << 28;
rv |= ((v >> 4) & 0xf) << 24;
rv |= ((v >> 8) & 0xf) << 20;
rv |= ((v >> 12) & 0xf) << 16;
rv |= ((v >> 16) & 0xf) << 12;
rv |= ((v >> 20) & 0xf) << 8;
rv |= ((v >> 24) & 0xf) << 4;
rv |= ((v >> 28) & 0xf) << 0;
return rv;
}
static uint64_t gen_secret (int i) {
assert (i > 0 && i < 256);
int iwrap = i & 0x7f; // wrap at 0x80;
uint32_t xor_lo = 0; // 0x40 flag
int idx; // mirror at 0x40;
if (iwrap & 0x40) {
xor_lo = 0x1;
idx = 0x80 - iwrap;
} else {
idx = iwrap;
}
int i16 = (idx >> 1) & 0xf;
if (idx & 0x20) {
i16 = 15 - i16;
}
uint32_t lo = baselut [i16];
uint32_t xk = xorlut [i16];
if (idx & 0x20) {
lo ^= 0xaaaaaaab;
xk ^= 0x10000000;
}
uint32_t hi = swapbytes32 (lo) ^ xk;
return ((uint64_t)hi << 32) | (lo ^ xor_lo);
}
PTFFormat::PTFFormat() {
}
PTFFormat::~PTFFormat() {
if (ptfunxored) {
free(ptfunxored);
}
}
bool
PTFFormat::foundin(std::string haystack, std::string needle) {
size_t found = haystack.find(needle);
if (found != std::string::npos) {
return true;
} else {
return false;
}
}
/* Return values: 0 success
0x01 to 0xff value of missing lut
-1 could not open file as ptf
*/
int
PTFFormat::load(std::string path, int64_t targetsr) {
FILE *fp;
unsigned char xxor[256];
unsigned char ct;
unsigned char v;
unsigned char voff;
uint64_t key;
uint64_t i;
uint64_t j;
int inv;
int err;
if (! (fp = fopen(path.c_str(), "rb"))) {
return -1;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
if (len < 0x40) {
fclose(fp);
return -1;
}
fseek(fp, 0x40, SEEK_SET);
fread(&c0, 1, 1, fp);
fread(&c1, 1, 1, fp);
// For version <= 7 support:
version = c0 & 0x0f;
c0 = c0 & 0xc0;
if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) {
/* Silently fail -- out of memory*/
fclose(fp);
ptfunxored = 0;
return -1;
}
switch (c0) {
case 0x00:
// Success! easy one
xxor[0] = c0;
xxor[1] = c1;
//fprintf(stderr, "0 %02x\n1 %02x\n", c0, c1);
for (i = 2; i < 256; i++) {
if (i%64 == 0) {
xxor[i] = c0;
} else {
xxor[i] = (xxor[i-1] + c1 - c0) & 0xff;
//fprintf(stderr, "%x %02x\n", i, xxor[i]);
}
}
break;
case 0x80:
//Success! easy two
xxor[0] = c0;
xxor[1] = c1;
for (i = 2; i < 256; i++) {
if (i%64 == 0) {
xxor[i] = c0;
} else {
xxor[i] = ((xxor[i-1] + c1 - c0) & 0xff);
}
}
for (i = 0; i < 64; i++) {
xxor[i] ^= 0x80;
}
for (i = 128; i < 192; i++) {
xxor[i] ^= 0x80;
}
break;
case 0x40:
case 0xc0:
xxor[0] = c0;
xxor[1] = c1;
for (i = 2; i < 256; i++) {
if (i%64 == 0) {
xxor[i] = c0;
} else {
xxor[i] = ((xxor[i-1] + c1 - c0) & 0xff);
}
}
key = gen_secret(c1);
for (i = 0; i < 64; i++) {
xxor[i] ^= (((key >> i) & 1) * 2 * 0x40) + 0x40;
}
for (i = 128; i < 192; i++) {
inv = (((key >> (i-128)) & 1) == 1) ? 1 : 3;
xxor[i] ^= (inv * 0x40);
}
for (i = 192; i < 256; i++) {
xxor[i] ^= 0x80;
}
break;
break;
default:
//Should not happen, failed c[0] c[1]
return -1;
break;
}
/* Read file */
i = 0;
fseek(fp, 0, SEEK_SET);
while (fread(&ct, 1, 1, fp) != 0) {
ptfunxored[i++] = ct;
}
fclose(fp);
/* version detection */
voff = 0x36;
v = ptfunxored[voff];
if (v == 0x20) {
voff += 7;
} else if (v == 0x03) {
voff += 4;
} else {
voff = 0;
}
v = ptfunxored[voff];
if (v == 10 || v == 11 || v == 12) {
version = v;
unxor10();
}
if (version == 0 || version == 5 || version == 7) {
/* Haven't detected version yet so decipher */
j = 0;
for (i = 0; i < len; i++) {
if (j%256 == 0) {
j = 0;
}
ptfunxored[i] ^= xxor[j];
j++;
}
/* version detection */
voff = 0x36;
v = ptfunxored[voff];
if (v == 0x20) {
voff += 7;
} else if (v == 0x03) {
voff += 4;
} else {
voff = 0;
}
v = ptfunxored[voff];
if (v == 5 || v == 7 || v == 8 || v == 9) {
version = v;
}
}
if (version < 5 || version > 12)
return -1;
targetrate = targetsr;
err = parse();
if (err)
return -1;
return 0;
}
uint8_t
PTFFormat::mostfrequent(uint32_t start, uint32_t stop)
{
uint32_t counts[256] = {0};
uint64_t i;
uint32_t max = 0;
uint8_t maxi = 0;
for (i = start; i < stop; i++) {
counts[ptfunxored[i]]++;
}
for (i = 0; i < 256; i++) {
if (counts[i] > max) {
maxi = i;
max = counts[i];
}
}
return maxi;
}
void
PTFFormat::unxor10(void)
{
uint64_t j;
uint8_t x = mostfrequent(0x1000, 0x2000);
uint8_t dx = 0x100-x;
for (j = 0x1000; j < len; j++) {
if(j % 0x1000 == 0xfff) {
x = (x - dx) & 0xff;
}
ptfunxored[j] ^= x;
}
}
int
PTFFormat::parse(void) {
if (version == 5) {
parse5header();
setrates();
if (sessionrate < 44100 || sessionrate > 192000)
return -1;
parseaudio5();
parserest5();
} else if (version == 7) {
parse7header();
setrates();
if (sessionrate < 44100 || sessionrate > 192000)
return -1;
parseaudio();
parserest89();
} else if (version == 8) {
parse8header();
setrates();
if (sessionrate < 44100 || sessionrate > 192000)
return -1;
parseaudio();
parserest89();
} else if (version == 9) {
parse9header();
setrates();
if (sessionrate < 44100 || sessionrate > 192000)
return -1;
parseaudio();
parserest89();
} else if (version == 10 || version == 11 || version == 12) {
parse10header();
setrates();
if (sessionrate < 44100 || sessionrate > 192000)
return -1;
parseaudio();
parserest10();
} else {
// Should not occur
return -1;
}
return 0;
}
void
PTFFormat::setrates(void) {
ratefactor = 1.f;
if (sessionrate != 0) {
ratefactor = (float)targetrate / sessionrate;
}
}
void
PTFFormat::parse5header(void) {
uint32_t k;
// Find session sample rate
k = 0x100;
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x02)) {
break;
}
k++;
}
sessionrate = 0;
sessionrate |= ptfunxored[k+12] << 16;
sessionrate |= ptfunxored[k+13] << 8;
sessionrate |= ptfunxored[k+14];
}
void
PTFFormat::parse7header(void) {
uint64_t k;
// Find session sample rate
k = 0x100;
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x05)) {
break;
}
k++;
}
sessionrate = 0;
sessionrate |= ptfunxored[k+12] << 16;
sessionrate |= ptfunxored[k+13] << 8;
sessionrate |= ptfunxored[k+14];
}
void
PTFFormat::parse8header(void) {
uint64_t k;
// Find session sample rate
k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x05)) {
break;
}
k++;
}
sessionrate = 0;
sessionrate |= ptfunxored[k+11];
sessionrate |= ptfunxored[k+12] << 8;
sessionrate |= ptfunxored[k+13] << 16;
}
void
PTFFormat::parse9header(void) {
uint64_t k;
// Find session sample rate
k = 0x100;
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x06)) {
break;
}
k++;
}
sessionrate = 0;
sessionrate |= ptfunxored[k+11];
sessionrate |= ptfunxored[k+12] << 8;
sessionrate |= ptfunxored[k+13] << 16;
}
void
PTFFormat::parse10header(void) {
uint64_t k;
// Find session sample rate
k = 0x100;
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x09)) {
break;
}
k++;
}
sessionrate = 0;
sessionrate |= ptfunxored[k+11];
sessionrate |= ptfunxored[k+12] << 8;
sessionrate |= ptfunxored[k+13] << 16;
}
void
PTFFormat::parserest5(void) {
uint64_t i, j, k;
uint64_t regionspertrack, lengthofname;
uint64_t startbytes, lengthbytes, offsetbytes;
uint16_t tracknumber = 0;
uint16_t findex;
uint16_t rindex;
k = 0;
for (i = 0; i < 5; i++) {
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x03)) {
break;
}
k++;
}
k++;
}
k--;
for (i = 0; i < 2; i++) {
while (k) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x01)) {
break;
}
k--;
}
if (k)
k--;
}
k++;
rindex = 0;
while (k < len) {
if ( (ptfunxored[k ] == 0xff) &&
(ptfunxored[k+1] == 0xff)) {
break;
}
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x01)) {
break;
}
k++;
}
lengthofname = ptfunxored[k+12];
if (ptfunxored[k+13] == 0x5a) {
k++;
break;
}
char name[256] = {0};
for (j = 0; j < lengthofname; j++) {
name[j] = ptfunxored[k+13+j];
}
name[j] = '\0';
regionspertrack = ptfunxored[k+13+j+3];
for (i = 0; i < regionspertrack; i++) {
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x03)) {
break;
}
k++;
}
j = k+16;
startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
//somethingbytes = (ptfunxored[j+1] & 0xf);
findex = ptfunxored[k+14];
j--;
uint32_t start = 0;
switch (startbytes) {
case 4:
start |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
start |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
start |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
start |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=startbytes;
uint32_t length = 0;
switch (lengthbytes) {
case 4:
length |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
length |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
length |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
length |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=lengthbytes;
uint32_t sampleoffset = 0;
switch (offsetbytes) {
case 4:
sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
sampleoffset |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=offsetbytes;
//printf("name=`%s` start=%04x length=%04x offset=%04x findex=%d\n", name,start,length,sampleoffset,findex);
std::string filename = string(name) + extension;
wav_t f = {
filename,
findex,
(int64_t)(start*ratefactor),
(int64_t)(length*ratefactor),
};
vector<wav_t>::iterator begin = audiofiles.begin();
vector<wav_t>::iterator finish = audiofiles.end();
vector<wav_t>::iterator found;
// Add file to lists
if ((found = std::find(begin, finish, f)) != finish) {
region_t r = {
name,
rindex,
(int64_t)(start*ratefactor),
(int64_t)(sampleoffset*ratefactor),
(int64_t)(length*ratefactor),
*found,
};
regions.push_back(r);
vector<track_t>::iterator ti;
vector<track_t>::iterator bt = tracks.begin();
vector<track_t>::iterator et = tracks.end();
track_t tr = { name, 0, 0, r };
if ((ti = std::find(bt, et, tr)) != et) {
tracknumber = (*ti).index;
} else {
tracknumber = tracks.size() + 1;
}
track_t t = {
name,
(uint16_t)tracknumber,
uint8_t(0),
r
};
tracks.push_back(t);
} else {
region_t r = {
name,
rindex,
(int64_t)(start*ratefactor),
(int64_t)(sampleoffset*ratefactor),
(int64_t)(length*ratefactor),
f,
};
regions.push_back(r);
vector<track_t>::iterator ti;
vector<track_t>::iterator bt = tracks.begin();
vector<track_t>::iterator et = tracks.end();
track_t tr = { name, 0, 0, r };
if ((ti = std::find(bt, et, tr)) != et) {
tracknumber = (*ti).index;
} else {
tracknumber = tracks.size() + 1;
}
track_t t = {
name,
(uint16_t)tracknumber,
uint8_t(0),
r
};
tracks.push_back(t);
}
rindex++;
k++;
}
k++;
}
}
void
PTFFormat::resort(std::vector<wav_t>& ws) {
int j = 0;
std::sort(ws.begin(), ws.end());
for (std::vector<wav_t>::iterator i = ws.begin(); i != ws.end(); ++i) {
(*i).index = j;
j++;
}
}
void
PTFFormat::parseaudio5(void) {
uint64_t i,k,l;
uint64_t lengthofname, wavnumber;
// Find end of wav file list
k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 0x5f) &&
(ptfunxored[k+1] == 0x50) &&
(ptfunxored[k+2] == 0x35)) {
break;
}
k++;
}
k++;
while (k < len) {
if ( (ptfunxored[k ] == 0x5f) &&
(ptfunxored[k+1] == 0x50) &&
(ptfunxored[k+2] == 0x35)) {
break;
}
k++;
}
// Find actual wav names
uint16_t numberofwavs = ptfunxored[k-23];
char wavname[256];
for (i = k; i < len; i++) {
if ( (ptfunxored[i ] == 'F') &&
(ptfunxored[i+1] == 'i') &&
(ptfunxored[i+2] == 'l') &&
(ptfunxored[i+3] == 'e') &&
(ptfunxored[i+4] == 's')) {
break;
}
}
wavnumber = 0;
i+=16;
char ext[5];
while (i < len && numberofwavs > 0) {
i++;
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x00) &&
(ptfunxored[i+2] == 0x05)) {
break;
}
lengthofname = ptfunxored[i];
i++;
l = 0;
while (l < lengthofname) {
wavname[l] = ptfunxored[i+l];
l++;
}
i+=lengthofname;
ext[0] = ptfunxored[i++];
ext[1] = ptfunxored[i++];
ext[2] = ptfunxored[i++];
ext[3] = ptfunxored[i++];
ext[4] = '\0';
wavname[l] = 0;
if (foundin(wavname, ".L") || foundin(wavname, ".R")) {
extension = string("");
} else if (foundin(wavname, ".wav") || foundin(ext, "WAVE")) {
extension = string(".wav");
} else if (foundin(wavname, ".aif") || foundin(ext, "AIFF")) {
extension = string(".aif");
} else {
extension = string("");
}
std::string wave = string(wavname);
wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
if (foundin(wave, string(".grp"))) {
continue;
}
actualwavs.push_back(f);
audiofiles.push_back(f);
//printf("done\n");
numberofwavs--;
i += 7;
}
resort(actualwavs);
resort(audiofiles);
}
void
PTFFormat::parseaudio(void) {
uint64_t i,j,k,l;
// Find end of wav file list
k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 0xff) &&
(ptfunxored[k+1] == 0xff) &&
(ptfunxored[k+2] == 0xff) &&
(ptfunxored[k+3] == 0xff)) {
break;
}
k++;
}
// Find actual wav names
bool first = true;
uint16_t numberofwavs;
char wavname[256];
for (i = k; i > 4; i--) {
if ( ((ptfunxored[i ] == 'W') || (ptfunxored[i ] == 'A')) &&
((ptfunxored[i-1] == 'A') || (ptfunxored[i-1] == 'I')) &&
((ptfunxored[i-2] == 'V') || (ptfunxored[i-2] == 'F')) &&
((ptfunxored[i-3] == 'E') || (ptfunxored[i-3] == 'F'))) {
j = i-4;
l = 0;
while (ptfunxored[j] != '\0') {
wavname[l] = ptfunxored[j];
l++;
j--;
}
wavname[l] = 0;
if (ptfunxored[i] == 'W') {
extension = string(".wav");
} else {
extension = string(".aif");
}
//uint8_t playlist = ptfunxored[j-8];
if (first) {
first = false;
for (j = k; j > 4; j--) {
if ( (ptfunxored[j ] == 0x01) &&
(ptfunxored[j-1] == 0x5a)) {
numberofwavs = 0;
numberofwavs |= (uint32_t)(ptfunxored[j-2] << 24);
numberofwavs |= (uint32_t)(ptfunxored[j-3] << 16);
numberofwavs |= (uint32_t)(ptfunxored[j-4] << 8);
numberofwavs |= (uint32_t)(ptfunxored[j-5]);
//printf("%d wavs\n", numberofwavs);
break;
}
k--;
}
}
std::string wave = string(wavname);
std::reverse(wave.begin(), wave.end());
wav_t f = { wave, (uint16_t)(numberofwavs - 1), 0, 0 };
if (foundin(wave, string(".grp"))) {
continue;
}
actualwavs.push_back(f);
numberofwavs--;
if (numberofwavs <= 0)
break;
}
}
}
void
PTFFormat::parserest89(void) {
uint64_t i,j,k,l;
// Find Regions
uint8_t startbytes = 0;
uint8_t lengthbytes = 0;
uint8_t offsetbytes = 0;
uint8_t somethingbytes = 0;
uint8_t skipbytes = 0;
k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 'S') &&
(ptfunxored[k+1] == 'n') &&
(ptfunxored[k+2] == 'a') &&
(ptfunxored[k+3] == 'p')) {
break;
}
k++;
}
uint16_t rindex = 0;
uint32_t findex = 0;
for (i = k; i < len-70; i++) {
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x0a)) {
break;
}
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x0c)) {
uint8_t lengthofname = ptfunxored[i+9];
char name[256] = {0};
for (j = 0; j < lengthofname; j++) {
name[j] = ptfunxored[i+13+j];
}
name[j] = '\0';
j += i+13;
//uint8_t disabled = ptfunxored[j];
offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
somethingbytes = (ptfunxored[j+3] & 0xf);
skipbytes = ptfunxored[j+4];
findex = ptfunxored[j+5
+startbytes
+lengthbytes
+offsetbytes
+somethingbytes
+skipbytes
+40];
/*rindex = ptfunxored[j+5
+startbytes
+lengthbytes
+offsetbytes
+somethingbytes
+skipbytes
+24];
*/
uint32_t sampleoffset = 0;
switch (offsetbytes) {
case 4:
sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
sampleoffset |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=offsetbytes;
uint32_t length = 0;
switch (lengthbytes) {
case 4:
length |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
length |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
length |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
length |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=lengthbytes;
uint32_t start = 0;
switch (startbytes) {
case 4:
start |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
start |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
start |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
start |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=startbytes;
/*
uint32_t something = 0;
switch (somethingbytes) {
case 4:
something |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
something |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
something |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
something |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=somethingbytes;
*/
std::string filename = string(name) + extension;
wav_t f = {
filename,
0,
(int64_t)(start*ratefactor),
(int64_t)(length*ratefactor),
};
f.index = findex;
//printf("something=%d\n", something);
vector<wav_t>::iterator begin = actualwavs.begin();
vector<wav_t>::iterator finish = actualwavs.end();
vector<wav_t>::iterator found;
// Add file to list only if it is an actual wav
if ((found = std::find(begin, finish, f)) != finish) {
audiofiles.push_back(f);
// Also add plain wav as region
region_t r = {
name,
rindex,
(int64_t)(start*ratefactor),
(int64_t)(sampleoffset*ratefactor),
(int64_t)(length*ratefactor),
f
};
regions.push_back(r);
// Region only
} else {
if (foundin(filename, string(".grp"))) {
continue;
}
region_t r = {
name,
rindex,
(int64_t)(start*ratefactor),
(int64_t)(sampleoffset*ratefactor),
(int64_t)(length*ratefactor),
f
};
regions.push_back(r);
}
rindex++;
}
}
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x03)) {
break;
}
k++;
}
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x02)) {
break;
}
k++;
}
k++;
// Tracks
uint32_t offset;
uint32_t tracknumber = 0;
uint32_t regionspertrack = 0;
for (;k < len; k++) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x04)) {
break;
}
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x02)) {
uint8_t lengthofname = 0;
lengthofname = ptfunxored[k+9];
if (lengthofname == 0x5a) {
continue;
}
track_t tr;
regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
//printf("regions/track=%d\n", regionspertrack);
char name[256] = {0};
for (j = 0; j < lengthofname; j++) {
name[j] = ptfunxored[j+k+13];
}
name[j] = '\0';
tr.name = string(name);
tr.index = tracknumber++;
for (j = k; regionspertrack > 0 && j < len; j++) {
for (l = j; l < len; l++) {
if ( (ptfunxored[l ] == 0x5a) &&
(ptfunxored[l+1] == 0x07)) {
j = l;
break;
}
}
if (regionspertrack == 0) {
// tr.reg.index = (uint8_t)ptfunxored[j+13+lengthofname+5];
break;
} else {
tr.reg.index = (uint8_t)(ptfunxored[l+11]);
vector<region_t>::iterator begin = regions.begin();
vector<region_t>::iterator finish = regions.end();
vector<region_t>::iterator found;
if ((found = std::find(begin, finish, tr.reg)) != finish) {
tr.reg = (*found);
}
i = l+16;
offset = 0;
offset |= (uint32_t)(ptfunxored[i+3] << 24);
offset |= (uint32_t)(ptfunxored[i+2] << 16);
offset |= (uint32_t)(ptfunxored[i+1] << 8);
offset |= (uint32_t)(ptfunxored[i]);
tr.reg.startpos = (int64_t)(offset*ratefactor);
if (tr.reg.length > 0) {
tracks.push_back(tr);
}
regionspertrack--;
}
}
}
}
}
void
PTFFormat::parserest10(void) {
uint64_t i,j,k,l;
// Find Regions
uint8_t startbytes = 0;
uint8_t lengthbytes = 0;
uint8_t offsetbytes = 0;
uint8_t somethingbytes = 0;
uint8_t skipbytes = 0;
k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 'S') &&
(ptfunxored[k+1] == 'n') &&
(ptfunxored[k+2] == 'a') &&
(ptfunxored[k+3] == 'p')) {
break;
}
k++;
}
for (i = k; i < len-70; i++) {
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x02)) {
k = i;
break;
}
}
k++;
for (i = k; i < len-70; i++) {
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x02)) {
k = i;
break;
}
}
k++;
uint16_t rindex = 0;
uint32_t findex = 0;
for (i = k; i < len-70; i++) {
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x08)) {
break;
}
if ( (ptfunxored[i ] == 0x5a) &&
(ptfunxored[i+1] == 0x01)) {
uint8_t lengthofname = ptfunxored[i+9];
if (ptfunxored[i+13] == 0x5a) {
continue;
}
char name[256] = {0};
for (j = 0; j < lengthofname; j++) {
name[j] = ptfunxored[i+13+j];
}
name[j] = '\0';
j += i+13;
//uint8_t disabled = ptfunxored[j];
//printf("%s\n", name);
offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
somethingbytes = (ptfunxored[j+3] & 0xf);
skipbytes = ptfunxored[j+4];
findex = ptfunxored[j+5
+startbytes
+lengthbytes
+offsetbytes
+somethingbytes
+skipbytes
+37];
/*rindex = ptfunxored[j+5
+startbytes
+lengthbytes
+offsetbytes
+somethingbytes
+skipbytes
+24];
*/
uint32_t sampleoffset = 0;
switch (offsetbytes) {
case 4:
sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
sampleoffset |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=offsetbytes;
uint32_t length = 0;
switch (lengthbytes) {
case 4:
length |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
length |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
length |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
length |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=lengthbytes;
uint32_t start = 0;
switch (startbytes) {
case 4:
start |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
start |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
start |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
start |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=startbytes;
/*
uint32_t something = 0;
switch (somethingbytes) {
case 4:
something |= (uint32_t)(ptfunxored[j+8] << 24);
case 3:
something |= (uint32_t)(ptfunxored[j+7] << 16);
case 2:
something |= (uint32_t)(ptfunxored[j+6] << 8);
case 1:
something |= (uint32_t)(ptfunxored[j+5]);
default:
break;
}
j+=somethingbytes;
*/
std::string filename = string(name) + extension;
wav_t f = {
filename,
0,
(int64_t)(start*ratefactor),
(int64_t)(length*ratefactor),
};
if (strlen(name) == 0) {
continue;
}
if (length == 0) {
continue;
}
f.index = findex;
//printf("something=%d\n", something);
vector<wav_t>::iterator begin = actualwavs.begin();
vector<wav_t>::iterator finish = actualwavs.end();
vector<wav_t>::iterator found;
// Add file to list only if it is an actual wav
if ((found = std::find(begin, finish, f)) != finish) {
audiofiles.push_back(f);
// Also add plain wav as region
region_t r = {
name,
rindex,
(int64_t)(start*ratefactor),
(int64_t)(sampleoffset*ratefactor),
(int64_t)(length*ratefactor),
f
};
regions.push_back(r);
// Region only
} else {
if (foundin(filename, string(".grp"))) {
continue;
}
region_t r = {
name,
rindex,
(int64_t)(start*ratefactor),
(int64_t)(sampleoffset*ratefactor),
(int64_t)(length*ratefactor),
f
};
regions.push_back(r);
}
rindex++;
//printf("%s\n", name);
}
}
// Tracks
uint32_t offset;
uint32_t tracknumber = 0;
uint32_t regionspertrack = 0;
for (;k < len; k++) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x08)) {
break;
}
}
k++;
for (;k < len; k++) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x04)) {
break;
}
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x02)) {
uint8_t lengthofname = 0;
lengthofname = ptfunxored[k+9];
if (lengthofname == 0x5a) {
continue;
}
track_t tr;
regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
//printf("regions/track=%d\n", regionspertrack);
char name[256] = {0};
for (j = 0; j < lengthofname; j++) {
name[j] = ptfunxored[j+k+13];
}
name[j] = '\0';
tr.name = string(name);
tr.index = tracknumber++;
for (j = k; regionspertrack > 0 && j < len; j++) {
for (l = j; l < len; l++) {
if ( (ptfunxored[l ] == 0x5a) &&
(ptfunxored[l+1] == 0x08)) {
j = l+1;
break;
}
}
if (regionspertrack == 0) {
// tr.reg.index = (uint8_t)ptfunxored[j+13+lengthofname+5];
break;
} else {
tr.reg.index = (uint8_t)(ptfunxored[l+11]);
vector<region_t>::iterator begin = regions.begin();
vector<region_t>::iterator finish = regions.end();
vector<region_t>::iterator found;
if ((found = std::find(begin, finish, tr.reg)) != finish) {
tr.reg = (*found);
}
i = l+16;
offset = 0;
offset |= (uint32_t)(ptfunxored[i+3] << 24);
offset |= (uint32_t)(ptfunxored[i+2] << 16);
offset |= (uint32_t)(ptfunxored[i+1] << 8);
offset |= (uint32_t)(ptfunxored[i]);
tr.reg.startpos = (int64_t)(offset*ratefactor);
if (tr.reg.length > 0) {
tracks.push_back(tr);
}
regionspertrack--;
}
}
}
}
}