9f107b5f80
- fetch: Go CLI tool for searching, downloading, and extracting AKAI sampler ISOs from archive.org - scripts/extract_wavs.sh: Shell script driving akaiutil to convert samples to WAV - Dockerfile: Multi-stage build packaging akaiutil + fetch - third_party/akaiutil: Vendored akaiutil v4.6.7 source (GPLv2) - docs/akaiutil.md: Full akaiutil reference
2941 lines
85 KiB
C
Executable File
2941 lines
85 KiB
C
Executable File
/*
|
|
* Copyright (C) 2010,2012,2018,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
|
*
|
|
* m.indlekofer@gmx.de
|
|
*
|
|
* 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 "commoninclude.h"
|
|
#include "akaiutil.h"
|
|
#include "akaiutil_file.h"
|
|
#include "akaiutil_wav.h"
|
|
|
|
|
|
|
|
/* AKAI file info */
|
|
int
|
|
akai_file_info(struct file_s *fp,int verbose)
|
|
{
|
|
static u_char hdrbuf[AKAI_FL_BLOCKSIZE]; /* XXX enough */
|
|
u_int hdrsize;
|
|
struct akai_genfilehdr_s *hdrp;
|
|
static char nbuf[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
int s900flag;
|
|
int sampleflag;
|
|
int programflag;
|
|
int cuelistflag;
|
|
int takelistflag;
|
|
int drum1000flag;
|
|
u_int i;
|
|
|
|
if ((fp==NULL)
|
|
||(fp->volp==NULL)
|
|
||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
if (verbose){
|
|
PRINTF_OUT("%s\n",fp->name);
|
|
PRINTF_OUT("fnr: %u\n",fp->index+1);
|
|
PRINTF_OUT("start: block 0x%04x\n",fp->bstart);
|
|
PRINTF_OUT("size: %u bytes\n",fp->size);
|
|
/* file type */
|
|
PRINTF_OUT("type: ");
|
|
hdrsize=sizeof(struct akai_genfilehdr_s); /* default */
|
|
s900flag=0; /* default */
|
|
sampleflag=0; /* default */
|
|
programflag=0; /* default */
|
|
cuelistflag=0; /* default */
|
|
takelistflag=0; /* default */
|
|
drum1000flag=0; /* default */
|
|
switch (fp->type){
|
|
case AKAI_SAMPLE900_FTYPE: /* S900 sample file */
|
|
PRINTF_OUT("S900 sample\n");
|
|
hdrsize=sizeof(struct akai_sample900_s);
|
|
s900flag=1;
|
|
sampleflag=1;
|
|
break;
|
|
case AKAI_SAMPLE1000_FTYPE: /* S1000 sample file */
|
|
PRINTF_OUT("S1000 sample\n");
|
|
hdrsize=sizeof(struct akai_sample1000_s);
|
|
sampleflag=1;
|
|
break;
|
|
case AKAI_SAMPLE3000_FTYPE: /* S3000 sample file */
|
|
PRINTF_OUT("S3000 sample\n");
|
|
hdrsize=sizeof(struct akai_sample3000_s);
|
|
sampleflag=1;
|
|
break;
|
|
case AKAI_CDSAMPLE3000_FTYPE: /* CD3000 CD-ROM sample parameters file */
|
|
PRINTF_OUT("CD3000 CD-ROM sample parameters\n");
|
|
/* Note: contains S3000 sample header */
|
|
hdrsize=sizeof(struct akai_sample3000_s);
|
|
sampleflag=1;
|
|
break;
|
|
case AKAI_PROGRAM900_FTYPE: /* S900 program file */
|
|
PRINTF_OUT("S900 program\n");
|
|
s900flag=1;
|
|
programflag=1;
|
|
break;
|
|
case AKAI_PROGRAM1000_FTYPE: /* S1000 program file */
|
|
PRINTF_OUT("S1000 program\n");
|
|
programflag=1;
|
|
break;
|
|
case AKAI_PROGRAM3000_FTYPE: /* S3000 program file */
|
|
PRINTF_OUT("S3000 program\n");
|
|
programflag=1;
|
|
break;
|
|
case AKAI_DRUM900_FTYPE: /* S900/S950 drum settings file */
|
|
PRINTF_OUT("S900/S950 drum settings\n");
|
|
/*s900flag=1;*/
|
|
/* S900/S950 drum settings info */
|
|
return akai_drum900_info(fp);
|
|
case AKAI_DRUM1000_FTYPE: /* S1000 or S3000 drum settings file */
|
|
PRINTF_OUT("S1000/S3000 drum settings\n");
|
|
drum1000flag=1;
|
|
break;
|
|
case AKAI_FXFILE_FTYPE: /* S1100 or S3000 effects file */
|
|
PRINTF_OUT("S1100/S3000 effects\n");
|
|
break;
|
|
case AKAI_QLFILE_FTYPE: /* S1100 or S3000 cue-list file */
|
|
PRINTF_OUT("S1100/S3000 cue-list\n");
|
|
cuelistflag=1;
|
|
break;
|
|
case AKAI_TLFILE_FTYPE: /* S1100 or S3000 take-list file */
|
|
PRINTF_OUT("S1100/S3000 take-list\n");
|
|
takelistflag=1;
|
|
break;
|
|
case AKAI_MULTI3000_FTYPE: /* S3000 multi file */
|
|
PRINTF_OUT("S3000 multi\n");
|
|
break; /* use generic file header */
|
|
case AKAI_FIXUP900_FTYPE: /* S900 fixup file */
|
|
PRINTF_OUT("S900 fixup\n");
|
|
/*s900flag=1;*/
|
|
return 0; /* done */
|
|
case AKAI_MEMIMG900_FTYPE: /* S900 memory image file */
|
|
PRINTF_OUT("S900 memory image\n");
|
|
/*s900flag=1;*/
|
|
return 0; /* done */
|
|
case AKAI_SYS1000_FTYPE: /* S1000 operating system file */
|
|
PRINTF_OUT("S1000 operating system\n");
|
|
return 0; /* done */
|
|
case AKAI_SYS3000_FTYPE: /* S3000 operating system file */
|
|
PRINTF_OUT("S3000 operating system\n");
|
|
return 0; /* done */
|
|
case AKAI_OVS900_FTYPE: /* S900 overall settings file */
|
|
PRINTF_OUT("S900 overall settings\n");
|
|
/*s900flag=1;*/
|
|
/* S900 overall settings info */
|
|
return akai_ovs900_info(fp);
|
|
case AKAI_CDSETUP3000_FTYPE:
|
|
/* CD3000 CD-ROM setup file */
|
|
/* Note: generic file header does not apply for this file type! */
|
|
PRINTF_OUT("CD3000 CD-ROM setup\n");
|
|
return akai_cdsetup3000_info(fp);
|
|
default:
|
|
/* unknown or unsupported */
|
|
PRINTF_OUT("\?\?\?\n");
|
|
return 1; /* no error */
|
|
}
|
|
|
|
/* read header */
|
|
if (akai_read_file(0,hdrbuf,fp,0,hdrsize)<0){
|
|
PRINTF_ERR("cannot read header\n");
|
|
return -1;
|
|
}
|
|
|
|
/* name */
|
|
if (s900flag){ /* S900 type? */
|
|
/* Note: name in S900 sample/program file header starts at byte 0 */
|
|
akai2ascii_name(hdrbuf,nbuf,1); /* 1: S900 */
|
|
}else{
|
|
/* generic file header */
|
|
hdrp=(struct akai_genfilehdr_s *)hdrbuf;
|
|
akai2ascii_name(hdrp->name,nbuf,0); /* 0: not S900 */
|
|
}
|
|
PRINTF_OUT("ramname: \"%s\"\n",nbuf);
|
|
if (sampleflag){
|
|
/* sample info */
|
|
akai_sample_info(fp,hdrbuf);
|
|
}else if (programflag){
|
|
/* program info */
|
|
return akai_program_info(fp);
|
|
}else if (cuelistflag){
|
|
/* cue-list info */
|
|
return akai_cuelist_info(fp);
|
|
}else if (takelistflag){
|
|
/* take-list info */
|
|
return akai_takelist_info(fp);
|
|
}else if (drum1000flag){
|
|
/* S1000/S3000 drum settings info */
|
|
return akai_drum1000_info(fp);
|
|
}
|
|
}else{
|
|
PRINTF_OUT("%3u %-16s %9u 0x%04x ",fp->index+1,fp->name,fp->size,fp->bstart);
|
|
if (fp->volp->type==AKAI_VOL_TYPE_S900){
|
|
/* S900 volume */
|
|
if (fp->osver!=0){ /* compressed file? */
|
|
/* number of un-compressed floppy blocks */
|
|
PRINTF_OUT(" %5u",fp->osver);
|
|
}
|
|
}else{
|
|
/* S1000/S3000 volume */
|
|
/* OS version */
|
|
if (((0xff&(fp->osver>>8))<100)&&((0xff&fp->osver)<100)){
|
|
PRINTF_OUT("%2u.%02u ",0xff&(fp->osver>>8),0xff&fp->osver);
|
|
}else{
|
|
PRINTF_OUT("%5u ",fp->osver);
|
|
}
|
|
/* tags */
|
|
for (i=0;i<AKAI_FILE_TAGNUM;i++){
|
|
if ((fp->tag[i]>=1)&&(fp->tag[i]<=AKAI_PARTHEAD_TAGNUM)){
|
|
PRINTF_OUT("%02u ",fp->tag[i]);
|
|
}else if ((fp->tag[i]==AKAI_FILE_TAGFREE)||(fp->tag[i]==AKAI_FILE_TAGS1000)){
|
|
PRINTF_OUT(" ");
|
|
}else{
|
|
PRINTF_OUT("? ");
|
|
}
|
|
}
|
|
}
|
|
PRINTF_OUT("\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
akai_sample_info(struct file_s *fp,u_char *hdrp)
|
|
{
|
|
struct akai_sample3000_s *s3000hdrp;
|
|
struct akai_sample900_s *s900hdrp;
|
|
u_int samplecount;
|
|
u_int samplerate;
|
|
u_int i,j,k;
|
|
|
|
if ((fp==NULL)||(hdrp==NULL)){
|
|
return;
|
|
}
|
|
|
|
if (fp->type==AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample header */
|
|
s900hdrp=(struct akai_sample900_s *)hdrp;
|
|
/* number of samples */
|
|
/* XXX should be an even number */
|
|
samplecount=(s900hdrp->slen[3]<<24)
|
|
+(s900hdrp->slen[2]<<16)
|
|
+(s900hdrp->slen[1]<<8)
|
|
+s900hdrp->slen[0];
|
|
PRINTF_OUT("scount: 0x%08x (%9u)\n",samplecount,samplecount);
|
|
samplerate=(s900hdrp->srate[1]<<8)+s900hdrp->srate[0];
|
|
PRINTF_OUT("srate: %uHz\n",samplerate);
|
|
if (samplerate>0){
|
|
PRINTF_OUT("sdur: %.3lfms\n",1000.0*((double)samplecount)/((double)samplerate));
|
|
}
|
|
PRINTF_OUT("npitch: %.2lf\n",((double)((s900hdrp->npitch[1]<<8)+s900hdrp->npitch[0]))/16.0);
|
|
PRINTF_OUT("loud: %+i\n",(((int)(char)s900hdrp->loud[1])<<8)+((int)(u_char)s900hdrp->loud[0]));
|
|
PRINTF_OUT("dmadesa: 0x%02x%02x\n",
|
|
s900hdrp->dmadesa[1],
|
|
s900hdrp->dmadesa[0]);
|
|
PRINTF_OUT("locat: 0x%02x%02x%02x%02x\n",
|
|
s900hdrp->locat[3],
|
|
s900hdrp->locat[2],
|
|
s900hdrp->locat[1],
|
|
s900hdrp->locat[0]);
|
|
PRINTF_OUT("start: 0x%02x%02x%02x%02x\n",
|
|
s900hdrp->start[3],
|
|
s900hdrp->start[2],
|
|
s900hdrp->start[1],
|
|
s900hdrp->start[0]);
|
|
PRINTF_OUT("end: 0x%02x%02x%02x%02x\n",
|
|
s900hdrp->end[3],
|
|
s900hdrp->end[2],
|
|
s900hdrp->end[1],
|
|
s900hdrp->end[0]);
|
|
PRINTF_OUT("llen: 0x%02x%02x%02x%02x\n",
|
|
s900hdrp->llen[3],
|
|
s900hdrp->llen[2],
|
|
s900hdrp->llen[1],
|
|
s900hdrp->llen[0]);
|
|
PRINTF_OUT("pmode: ");
|
|
switch (s900hdrp->pmode){
|
|
case SAMPLE900_PMODE_ONESHOT:
|
|
PRINTF_OUT("ONESHOT\n");
|
|
break;
|
|
case SAMPLE900_PMODE_LOOP:
|
|
PRINTF_OUT("LOOP\n");
|
|
break;
|
|
case SAMPLE900_PMODE_ALTLOOP:
|
|
PRINTF_OUT("ALTLOOP\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT("dir: ");
|
|
switch (s900hdrp->dir){
|
|
case SAMPLE900_DIR_NORM:
|
|
PRINTF_OUT("NORM\n");
|
|
break;
|
|
case SAMPLE900_DIR_REV:
|
|
PRINTF_OUT("REV\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT("type: ");
|
|
switch (s900hdrp->type){
|
|
case SAMPLE900_TYPE_NORM:
|
|
PRINTF_OUT("NORM\n");
|
|
break;
|
|
case SAMPLE900_TYPE_VELXF:
|
|
PRINTF_OUT("VELXF\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT("compr: %s\n",
|
|
(fp->osver!=0)?"ON":"OFF"); /* S900 compressed/non-compressed sample format */
|
|
}else if ((fp->type==AKAI_SAMPLE1000_FTYPE)
|
|
||(fp->type==AKAI_SAMPLE3000_FTYPE)
|
|
||(fp->type==AKAI_CDSAMPLE3000_FTYPE)){
|
|
/* S1000/S3000 sample header */
|
|
s3000hdrp=(struct akai_sample3000_s *)hdrp;
|
|
/* Note: S1000 header is contained within S3000 header */
|
|
/* number of samples */
|
|
samplecount=(s3000hdrp->s1000.slen[3]<<24)
|
|
+(s3000hdrp->s1000.slen[2]<<16)
|
|
+(s3000hdrp->s1000.slen[1]<<8)
|
|
+s3000hdrp->s1000.slen[0];
|
|
PRINTF_OUT("scount: 0x%08x (%9u)\n",samplecount,samplecount);
|
|
samplerate=(s3000hdrp->s1000.srate[1]<<8)+s3000hdrp->s1000.srate[0];
|
|
PRINTF_OUT("srate: %uHz\n",samplerate);
|
|
if (samplerate>0){
|
|
PRINTF_OUT("sdur: %.3lfms\n",1000.0*((double)samplecount)/((double)samplerate));
|
|
}
|
|
PRINTF_OUT("bandw: ");
|
|
switch (s3000hdrp->s1000.bandw){
|
|
case SAMPLE1000_BANDW_10KHZ:
|
|
PRINTF_OUT("10kHz\n");
|
|
break;
|
|
case SAMPLE1000_BANDW_20KHZ:
|
|
PRINTF_OUT("20kHz\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT("rkey: %u\n",s3000hdrp->s1000.rkey);
|
|
PRINTF_OUT("ctune: %+i\n",(int)(char)s3000hdrp->s1000.ctune);
|
|
PRINTF_OUT("stune: %+i\n",(int)(char)s3000hdrp->s1000.stune);
|
|
PRINTF_OUT("hltoff: %+i\n",(int)(char)s3000hdrp->s1000.hltoff);
|
|
k=(s3000hdrp->s1000.stpaira[1]<<8)+s3000hdrp->s1000.stpaira[0];
|
|
if (k!=AKAI_SAMPLE1000_STPAIRA_NONE){
|
|
if (fp->type==AKAI_SAMPLE3000_FTYPE){
|
|
k*=SAMPLE3000_STPAIRA_MULT;
|
|
PRINTF_OUT("stpaira: 0x%05x\n",k);
|
|
}else{
|
|
PRINTF_OUT("stpaira: 0x%04x\n",k);
|
|
}
|
|
}
|
|
PRINTF_OUT("locat: 0x%02x%02x%02x%02x\n",
|
|
s3000hdrp->s1000.locat[3],
|
|
s3000hdrp->s1000.locat[2],
|
|
s3000hdrp->s1000.locat[1],
|
|
s3000hdrp->s1000.locat[0]);
|
|
PRINTF_OUT("start: 0x%02x%02x%02x%02x\n",
|
|
s3000hdrp->s1000.start[3],
|
|
s3000hdrp->s1000.start[2],
|
|
s3000hdrp->s1000.start[1],
|
|
s3000hdrp->s1000.start[0]);
|
|
PRINTF_OUT("end: 0x%02x%02x%02x%02x\n",
|
|
s3000hdrp->s1000.end[3],
|
|
s3000hdrp->s1000.end[2],
|
|
s3000hdrp->s1000.end[1],
|
|
s3000hdrp->s1000.end[0]);
|
|
PRINTF_OUT("pmode: ");
|
|
switch (s3000hdrp->s1000.pmode){
|
|
case SAMPLE1000_PMODE_LOOP:
|
|
PRINTF_OUT("LOOP\n");
|
|
break;
|
|
case SAMPLE1000_PMODE_LOOPNOTREL:
|
|
PRINTF_OUT("LOOPNOTREL\n");
|
|
break;
|
|
case SAMPLE1000_PMODE_NOLOOP:
|
|
PRINTF_OUT("NOLOOP\n");
|
|
break;
|
|
case SAMPLE1000_PMODE_TOEND:
|
|
PRINTF_OUT("TOEND\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT("lnum: %u\n",s3000hdrp->s1000.lnum);
|
|
PRINTF_OUT("lfirst: %u\n",s3000hdrp->s1000.lfirst+1);
|
|
for (i=0;i<AKAI_SAMPLE1000_LOOPNUM;i++){
|
|
k=(s3000hdrp->s1000.loop[i].time[1]<<8)+s3000hdrp->s1000.loop[i].time[0];
|
|
if (k==SAMPLE1000LOOP_TIME_NOLOOP){
|
|
continue; /* next loop */
|
|
}
|
|
j=(s3000hdrp->s1000.loop[i].at[3]<<24)
|
|
+(s3000hdrp->s1000.loop[i].at[2]<<16)
|
|
+(s3000hdrp->s1000.loop[i].at[1]<<8)
|
|
+s3000hdrp->s1000.loop[i].at[0];
|
|
if (j>=samplecount){ /* invalid? */
|
|
continue; /* next loop */
|
|
}
|
|
PRINTF_OUT("loop %u:\n",i+1);
|
|
PRINTF_OUT(" loopat: 0x%08x\n",j);
|
|
PRINTF_OUT(" length: 0x%02x%02x%02x%02x.0x%02x%02x\n",
|
|
s3000hdrp->s1000.loop[i].len[3],
|
|
s3000hdrp->s1000.loop[i].len[2],
|
|
s3000hdrp->s1000.loop[i].len[1],
|
|
s3000hdrp->s1000.loop[i].len[0],
|
|
s3000hdrp->s1000.loop[i].flen[1],
|
|
s3000hdrp->s1000.loop[i].flen[0]);
|
|
if (k==SAMPLE1000LOOP_TIME_HOLD){
|
|
PRINTF_OUT(" ltime: HOLD\n");
|
|
}else{
|
|
PRINTF_OUT(" ltime: %ums\n",k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
akai_program_info(struct file_s *fp)
|
|
{
|
|
static char nbuf[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
struct akai_program900_s *s900hdrp;
|
|
struct akai_program900kg_s *s900kgp;
|
|
struct akai_program3000_s *s3000hdrp;
|
|
struct akai_program3000kg_s *s3000kgp;
|
|
u_char *buf;
|
|
u_int hdrsiz;
|
|
u_int kgsiz;
|
|
u_int kgnum;
|
|
u_int i,j,k;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
if (fp->type==AKAI_PROGRAM900_FTYPE){
|
|
hdrsiz=sizeof(struct akai_program900_s);
|
|
kgsiz=sizeof(struct akai_program900kg_s);
|
|
}else if (fp->type==AKAI_PROGRAM1000_FTYPE){
|
|
hdrsiz=sizeof(struct akai_program1000_s);
|
|
kgsiz=sizeof(struct akai_program1000kg_s);
|
|
}else if (fp->type==AKAI_PROGRAM3000_FTYPE){
|
|
hdrsiz=sizeof(struct akai_program3000_s);
|
|
kgsiz=sizeof(struct akai_program3000kg_s);
|
|
}else{
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<hdrsiz){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
if (fp->type==AKAI_PROGRAM900_FTYPE){
|
|
/* S900 program header */
|
|
s900hdrp=(struct akai_program900_s *)buf;
|
|
PRINTF_OUT("kgxf: %s\n",(s900hdrp->kgxf!=0x00)?"ON":"OFF");
|
|
kgnum=s900hdrp->kgnum;
|
|
PRINTF_OUT("kgnum: %u\n",kgnum);
|
|
if (fp->size<hdrsiz+kgnum*kgsiz){
|
|
PRINTF_ERR("invalid file size\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
k=(s900hdrp->kg1a[1]<<8)+s900hdrp->kg1a[0];
|
|
if (k!=PROGRAM900_KGA_NONE){
|
|
PRINTF_OUT("kg1a: 0x%04x\n",k);
|
|
}
|
|
for (i=0;i<kgnum;i++){
|
|
PRINTF_OUT("keygroup %u:\n",i+1);
|
|
s900kgp=(struct akai_program900kg_s *)(buf+hdrsiz+i*kgsiz);
|
|
PRINTF_OUT(" midichoff: %u\n",s900kgp->midichoff);
|
|
PRINTF_OUT(" key lo-hi: %u-%u\n",s900kgp->keylo,s900kgp->keyhi);
|
|
PRINTF_OUT(" outch: ");
|
|
switch (s900kgp->outch1){
|
|
case PROGRAM900KG_OUTCH1_LEFT:
|
|
PRINTF_OUT("LEFT\n");
|
|
break;
|
|
case PROGRAM900KG_OUTCH1_RIGHT:
|
|
PRINTF_OUT("RIGHT\n");
|
|
break;
|
|
case PROGRAM900KG_OUTCH1_ANY:
|
|
PRINTF_OUT("ANY\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("%u\n",s900kgp->outch1+1);
|
|
break;
|
|
}
|
|
PRINTF_OUT(" pitch: %s\n",((PROGRAM900KG_FLAGS_PCONST&s900kgp->flags)!=0x00)?"CONST":"TRACK");
|
|
PRINTF_OUT(" oneshot: %s\n",((PROGRAM900KG_FLAGS_ONESHOT&s900kgp->flags)!=0x00)?"ON":"OFF");
|
|
PRINTF_OUT(" velxf: %s\n",((PROGRAM900KG_FLAGS_VELXF&s900kgp->flags)!=0x00)?"ON":"OFF");
|
|
PRINTF_OUT(" velxfv50: %u\n",s900kgp->velxfv50);
|
|
PRINTF_OUT(" velswth: %u",s900kgp->velswth);
|
|
if (s900kgp->velswth<=PROGRAM900KG_VELSWTH_NOSOFT){
|
|
PRINTF_OUT(" (no soft sample)\n");
|
|
}else if (s900kgp->velswth>=PROGRAM900KG_VELSWTH_NOLOUD){
|
|
PRINTF_OUT(" (no loud sample)\n");
|
|
}else{
|
|
PRINTF_OUT("\n");
|
|
}
|
|
PRINTF_OUT(" sample 1 (soft):\n");
|
|
PRINTF_OUT(" tune: %+.2lf\n",((double)((((int)(char)s900kgp->tune1[1])<<8)+((int)(u_char)s900kgp->tune1[0])))/16.0);
|
|
PRINTF_OUT(" filter: %u\n",s900kgp->filter1);
|
|
PRINTF_OUT(" loud: %+i\n",(int)(char)s900kgp->loud1);
|
|
akai2ascii_name(s900kgp->sname1,nbuf,1); /* 1: S900 */
|
|
PRINTF_OUT(" sname: \"%s\"\n",nbuf);
|
|
k=(s900kgp->shdra1[1]<<8)+s900kgp->shdra1[0];
|
|
if (k!=PROGRAM900KG_SHDRA_NONE){
|
|
PRINTF_OUT(" shdra: 0x%04x\n",k);
|
|
}
|
|
PRINTF_OUT(" sample 2 (loud):\n");
|
|
PRINTF_OUT(" tune: %+.2lf\n",((double)((((int)(char)s900kgp->tune2[1])<<8)+((int)(u_char)s900kgp->tune2[0])))/16.0);
|
|
PRINTF_OUT(" filter: %u\n",s900kgp->filter2);
|
|
PRINTF_OUT(" loud: %+i\n",(int)(char)s900kgp->loud2);
|
|
akai2ascii_name(s900kgp->sname2,nbuf,1); /* 1: S900 */
|
|
PRINTF_OUT(" sname: \"%s\"\n",nbuf);
|
|
k=(s900kgp->shdra2[1]<<8)+s900kgp->shdra2[0];
|
|
if (k!=PROGRAM900KG_SHDRA_NONE){
|
|
PRINTF_OUT(" shdra: 0x%04x\n",k);
|
|
}
|
|
k=(s900kgp->kgnexta[1]<<8)+s900kgp->kgnexta[0];
|
|
if (k!=PROGRAM900_KGA_NONE){
|
|
PRINTF_OUT(" kgnexta: 0x%04x\n",k);
|
|
}
|
|
}
|
|
}else{
|
|
/* S1000/S3000 program header */
|
|
s3000hdrp=(struct akai_program3000_s *)buf;
|
|
/* Note: S1000 header is contained within S3000 header */
|
|
PRINTF_OUT("midich: ");
|
|
if (s3000hdrp->s1000.midich1==PROGRAM1000_MIDICH1_OMNI){
|
|
PRINTF_OUT("OMNI\n");
|
|
}else{
|
|
PRINTF_OUT("%u\n",s3000hdrp->s1000.midich1+1);
|
|
}
|
|
PRINTF_OUT("key lo-hi: %u-%u\n",s3000hdrp->s1000.keylo,s3000hdrp->s1000.keyhi);
|
|
PRINTF_OUT("oct: %+i\n",(int)(char)s3000hdrp->s1000.oct);
|
|
PRINTF_OUT("auxch: ");
|
|
if (s3000hdrp->s1000.auxch1==PROGRAM1000_AUXCH1_OFF){
|
|
PRINTF_OUT("OFF\n");
|
|
}else{
|
|
PRINTF_OUT("%u\n",s3000hdrp->s1000.auxch1+1);
|
|
}
|
|
PRINTF_OUT("kgxf: %s\n",(s3000hdrp->s1000.kgxf!=0x00)?"ON":"OFF");
|
|
kgnum=s3000hdrp->s1000.kgnum;
|
|
PRINTF_OUT("kgnum: %u\n",kgnum);
|
|
if (fp->size<hdrsiz+kgnum*kgsiz){
|
|
PRINTF_ERR("invalid file size\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
k=(s3000hdrp->s1000.kg1a[1]<<8)+s3000hdrp->s1000.kg1a[0];
|
|
if (k!=PROGRAM1000_KGA_NONE){
|
|
if (fp->type==AKAI_PROGRAM3000_FTYPE){
|
|
k*=PROGRAM3000_KGA_MULT;
|
|
PRINTF_OUT("kg1a: 0x%05x\n",k);
|
|
}else{
|
|
PRINTF_OUT("kg1a: 0x%04x\n",k);
|
|
}
|
|
}
|
|
for (i=0;i<kgnum;i++){
|
|
PRINTF_OUT("keygroup %u:\n",i+1);
|
|
s3000kgp=(struct akai_program3000kg_s *)(buf+hdrsiz+i*kgsiz);
|
|
PRINTF_OUT(" key lo-hi: %u-%u\n",s3000kgp->s1000.keylo,s3000kgp->s1000.keyhi);
|
|
PRINTF_OUT(" ctune: %+i\n",(int)(char)s3000kgp->s1000.ctune);
|
|
PRINTF_OUT(" stune: %+i\n",(int)(char)s3000kgp->s1000.stune);
|
|
PRINTF_OUT(" filter: %u\n",s3000kgp->s1000.filter);
|
|
PRINTF_OUT(" velxf: %s\n",(s3000kgp->s1000.velxf!=0x00)?"ON":"OFF");
|
|
for (j=0;j<PROGRAM1000KG_VELZONENUM;j++){
|
|
PRINTF_OUT(" velzone %u:\n",j+1);
|
|
akai2ascii_name(s3000kgp->s1000.velzone[j].sname,nbuf,0); /* 0: not S900 */
|
|
PRINTF_OUT(" vel lo-hi: %u-%u\n",s3000kgp->s1000.velzone[j].vello,s3000kgp->s1000.velzone[j].velhi);
|
|
PRINTF_OUT(" ctune: %+i\n",(int)(char)s3000kgp->s1000.velzone[j].ctune);
|
|
PRINTF_OUT(" stune: %+i\n",(int)(char)s3000kgp->s1000.velzone[j].stune);
|
|
PRINTF_OUT(" loud: %+i\n",(int)(char)s3000kgp->s1000.velzone[j].loud);
|
|
PRINTF_OUT(" filter: %+i\n",(int)(char)s3000kgp->s1000.velzone[j].filter);
|
|
PRINTF_OUT(" pan: %+i\n",(int)(char)s3000kgp->s1000.velzone[j].pan);
|
|
PRINTF_OUT(" auxchoff: %u\n",s3000kgp->s1000.auxchoff[j]);
|
|
PRINTF_OUT(" pitch: %s\n",(s3000kgp->s1000.pconst[j]!=0x00)?"CONST":"TRACK");
|
|
PRINTF_OUT(" pmode: ");
|
|
switch (s3000kgp->s1000.velzone[j].pmode){
|
|
case PROGRAM1000_PMODE_SAMPLE:
|
|
PRINTF_OUT("SAMPLE\n");
|
|
break;
|
|
case PROGRAM1000_PMODE_LOOP:
|
|
PRINTF_OUT("LOOP\n");
|
|
break;
|
|
case PROGRAM1000_PMODE_LOOPNOTREL:
|
|
PRINTF_OUT("LOOPNOTREL\n");
|
|
break;
|
|
case PROGRAM1000_PMODE_NOLOOP:
|
|
PRINTF_OUT("NOLOOP\n");
|
|
break;
|
|
case PROGRAM1000_PMODE_TOEND:
|
|
PRINTF_OUT("TOEND\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT(" sname: \"%s\"\n",nbuf);
|
|
k=(s3000kgp->s1000.velzone[j].shdra[1]<<8)+s3000kgp->s1000.velzone[j].shdra[0];
|
|
if (k!=PROGRAM1000KG_SHDRA_NONE){
|
|
if (fp->type==AKAI_PROGRAM3000_FTYPE){
|
|
k*=PROGRAM3000_SHDRA_MULT;
|
|
PRINTF_OUT(" shdra: 0x%05x\n",k);
|
|
}else{
|
|
PRINTF_OUT(" shdra: 0x%04x\n",k);
|
|
}
|
|
}
|
|
}
|
|
k=(s3000kgp->s1000.kgnexta[1]<<8)+s3000kgp->s1000.kgnexta[0];
|
|
if (k!=PROGRAM1000_KGA_NONE){
|
|
if (fp->type==AKAI_PROGRAM3000_FTYPE){
|
|
k*=PROGRAM3000_KGA_MULT;
|
|
PRINTF_OUT(" kgnexta: 0x%05x\n",k);
|
|
}else{
|
|
PRINTF_OUT(" kgnexta: 0x%04x\n",k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
akai_cuelist_info(struct file_s *fp)
|
|
{
|
|
static char nbuf[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
struct akai_cuelist_s *hdrp;
|
|
struct akai_cue_s *cuep;
|
|
u_char *buf;
|
|
u_int cuenum;
|
|
char *tname;
|
|
u_int i;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<sizeof(struct akai_cuelist_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
hdrp=(struct akai_cuelist_s *)buf;
|
|
cuenum=(u_int)hdrp->cuenum;
|
|
PRINTF_OUT("cuenum: %u\n",cuenum);
|
|
if (fp->size<sizeof(struct akai_cuelist_s)+cuenum*sizeof(struct akai_cue_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
if (cuenum>0){
|
|
/* cues */
|
|
PRINTF_OUT("\ncue time type name mnote mvel lvl pan\n");
|
|
PRINTF_OUT("------------------------------------------------------------\n");
|
|
for (i=0;i<cuenum;i++){
|
|
cuep=(struct akai_cue_s *)(buf+sizeof(struct akai_cuelist_s)+i*sizeof(struct akai_cue_s));
|
|
akai2ascii_name(cuep->name,nbuf,0); /* 0: not S900 */
|
|
switch (cuep->type){
|
|
case AKAI_CUETYPE_MOFF:
|
|
tname="MOFF";
|
|
break;
|
|
case AKAI_CUETYPE_MON:
|
|
tname="MON ";
|
|
break;
|
|
case AKAI_CUETYPE_TOFF:
|
|
tname="TOFF";
|
|
break;
|
|
case AKAI_CUETYPE_TON:
|
|
tname="TON ";
|
|
break;
|
|
default:
|
|
tname="\?\?\? ";
|
|
break;
|
|
}
|
|
PRINTF_OUT("%3u %02x:%02x:%02x:%02x.%x %s %-12s ",
|
|
i+1,
|
|
(u_int)cuep->time[4],
|
|
(u_int)cuep->time[3],
|
|
(u_int)cuep->time[2],
|
|
(u_int)cuep->time[1],
|
|
(u_int)(cuep->time[0]>>4),
|
|
tname,
|
|
nbuf);
|
|
if ((cuep->type==AKAI_CUETYPE_MOFF)||(cuep->type==AKAI_CUETYPE_MON)){
|
|
PRINTF_OUT("%3u %3u\n",
|
|
(u_int)cuep->midinote,
|
|
(u_int)cuep->midivel);
|
|
}else if ((cuep->type==AKAI_CUETYPE_TOFF)||(cuep->type==AKAI_CUETYPE_TON)){
|
|
PRINTF_OUT(" %3u %+3i\n",
|
|
(u_int)cuep->stlvl,
|
|
(int)(char)cuep->pan);
|
|
}else{
|
|
PRINTF_OUT("\n");
|
|
}
|
|
}
|
|
PRINTF_OUT("------------------------------------------------------------\n");
|
|
}
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
akai_takelist_info(struct file_s *fp)
|
|
{
|
|
static char nbuf[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
struct akai_cuelist_s *hdrp;
|
|
struct akai_cue_s *cuep;
|
|
u_char *buf;
|
|
u_int cuenum;
|
|
u_int i;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<sizeof(struct akai_cuelist_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
hdrp=(struct akai_cuelist_s *)buf;
|
|
cuenum=(u_int)hdrp->cuenum;
|
|
PRINTF_OUT("cuenum: %u\n",cuenum);
|
|
if (fp->size<sizeof(struct akai_cuelist_s)+cuenum*sizeof(struct akai_cue_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
if (cuenum>0){
|
|
/* cues */
|
|
PRINTF_OUT("\ncue rep name mnote mch lvl pan fadein fadeout\n");
|
|
PRINTF_OUT("------------------------------------------------------------\n");
|
|
for (i=0;i<cuenum;i++){
|
|
cuep=(struct akai_cue_s *)(buf+sizeof(struct akai_cuelist_s)+i*sizeof(struct akai_cue_s));
|
|
akai2ascii_name(cuep->name,nbuf,0); /* 0: not S900 */
|
|
PRINTF_OUT("%3u %3u %-12s %3u %3u %3u %+3i %5u %5u\n",
|
|
i+1,
|
|
((u_int)cuep->repeat1)+1,
|
|
nbuf,
|
|
(u_int)cuep->midinote,
|
|
((u_int)cuep->midich1)+1,
|
|
(u_int)cuep->stlvl,
|
|
(int)(char)cuep->pan,
|
|
(((u_int)cuep->fadein[1])<<8)|((u_int)cuep->fadein[0]),
|
|
(((u_int)cuep->fadeout[1])<<8)|((u_int)cuep->fadeout[0]));
|
|
}
|
|
PRINTF_OUT("------------------------------------------------------------\n");
|
|
}
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
akai_drum1000_info(struct file_s *fp)
|
|
{
|
|
struct akai_drum1000_s *dfp;
|
|
struct akai_drum1000des_s *ddp;
|
|
u_char *buf;
|
|
u_int i,j;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<sizeof(struct akai_drum1000_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
dfp=(struct akai_drum1000_s *)buf;
|
|
ddp=dfp->ddes1; /* for ME35T unit 1 */
|
|
for (i=0;i<DRUM1000_UNITNUM;i++){
|
|
PRINTF_OUT("\nS1000/S3000 drum settings for ME35T unit %u:\n",i+1);
|
|
PRINTF_OUT("inp midich mnote sens trig vcurv captt recovt ontime\n");
|
|
PRINTF_OUT("------------------------------------------------------\n");
|
|
for (j=0;j<DRUM1000_INPUTNUM;j++){
|
|
PRINTF_OUT("%3u %3u %3u %3u %3u %3u %3ums %3ums %3ums\n",
|
|
j+1,
|
|
((u_int)ddp->midich1)+1,
|
|
(u_int)ddp->midinote,
|
|
(u_int)ddp->sens,
|
|
(u_int)ddp->trig,
|
|
((u_int)ddp->vcurv1)+1,
|
|
(u_int)ddp->captt,
|
|
(u_int)ddp->recovt,
|
|
(u_int)ddp->ontime);
|
|
}
|
|
PRINTF_OUT("------------------------------------------------------\n");
|
|
ddp=dfp->ddes2; /* for ME35T unit 2 */
|
|
}
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
akai_drum900_info(struct file_s *fp)
|
|
{
|
|
struct akai_drum900_s *dfp;
|
|
struct akai_drum900des_s *ddp;
|
|
u_char *buf;
|
|
u_int captt,ontime,recovt;
|
|
u_int j;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<sizeof(struct akai_drum900_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
dfp=(struct akai_drum900_s *)buf;
|
|
PRINTF_OUT("ASK90 enable: %s\n",dfp->ask90enab?"ON":"OFF");
|
|
PRINTF_OUT("ASK90 sensitivity: %s\n",dfp->ask90sens?"HIGH":"LOW");
|
|
PRINTF_OUT("\nS900/S950 drum settings for ASK90/ME35T:\n");
|
|
PRINTF_OUT("itype inp midich mnote gain trig vcurv captt ontime recovt resetba adcla\n");
|
|
PRINTF_OUT("----------------------------------------------------------------------------\n");
|
|
for (j=0;j<DRUM900_INPUTNUM;j++){
|
|
ddp=&dfp->ddes[j];
|
|
captt=((ddp->captt4[1]<<8)+ddp->captt4[0])>>2;
|
|
ontime=((ddp->ontime4[1]<<8)+ddp->ontime4[0])>>2;
|
|
recovt=((ddp->recovt4[1]<<8)+ddp->recovt4[0])>>2;
|
|
if (ddp->itype==DRUM900DES_ITYPE_ME35T){
|
|
/* for ME35T */
|
|
PRINTF_OUT("ME35T %3u %3u %3u %3u %3u %3u %3ums %3ums %3ums - -\n",
|
|
((u_int)ddp->inpnr1)+1,
|
|
((u_int)ddp->midich1)+1,
|
|
(u_int)ddp->midinote,
|
|
(u_int)ddp->gain,
|
|
(u_int)ddp->me35t_trig,
|
|
((u_int)ddp->me35t_vcurv1)+1,
|
|
captt,
|
|
ontime,
|
|
recovt);
|
|
}else{
|
|
/* for ASK90 */
|
|
PRINTF_OUT("ASK90 %3u %3u %3u %3u %3u - %3ums %3ums %3ums 0x%02x%02x 0x%02x%02x\n",
|
|
((u_int)ddp->inpnr1)+1,
|
|
((u_int)ddp->midich1)+1,
|
|
(u_int)ddp->midinote,
|
|
(u_int)ddp->gain,
|
|
(u_int)ddp->ask90_trig,
|
|
captt,
|
|
ontime,
|
|
recovt,
|
|
(u_int)ddp->ask90_resba[1],(u_int)ddp->ask90_resba[0],
|
|
(u_int)ddp->ask90_adcla[1],(u_int)ddp->ask90_adcla[0]);
|
|
}
|
|
}
|
|
PRINTF_OUT("----------------------------------------------------------------------------\n");
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
akai_ovs900_info(struct file_s *fp)
|
|
{
|
|
static char nbuf[AKAI_NAME_LEN_S900+1]; /* +1 for '\0' */
|
|
struct akai_ovs900_s *ofp;
|
|
u_char *buf;
|
|
u_int i;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<sizeof(struct akai_ovs900_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
ofp=(struct akai_ovs900_s *)buf;
|
|
akai2ascii_name((u_char *)ofp->progname,nbuf,1); /* 1: S900 */
|
|
PRINTF_OUT("selected program name: \"%s\"\n",nbuf);
|
|
i=(ofp->testmidich[1]<<8)+ofp->testmidich[0];
|
|
PRINTF_OUT("test MIDI channel: %u\n",i);
|
|
i=(ofp->testmidikey[1]<<8)+ofp->testmidikey[0];
|
|
PRINTF_OUT("test MIDI key: %u\n",i);
|
|
i=(ofp->testmidivel[1]<<8)+ofp->testmidivel[0];
|
|
PRINTF_OUT("test MIDI velocity: %u\n",i);
|
|
PRINTF_OUT("basic MIDI channel: %u\n",((u_int)(OVS900_BMIDICH1MASK&ofp->bmidich1omni))+1);
|
|
PRINTF_OUT("MIDI OMNI: %s\n",(OVS900_OMNIMASK&ofp->bmidich1omni)?"ON":"OFF");
|
|
PRINTF_OUT("loudness: %s\n",ofp->loudness?"ON":"OFF");
|
|
PRINTF_OUT("control port: ");
|
|
switch (ofp->ctrlport){
|
|
case OVS900_CTRLPORT_MIDI:
|
|
PRINTF_OUT("MIDI\n");
|
|
break;
|
|
case OVS900_CTRLPORT_RS232:
|
|
PRINTF_OUT("RS232\n");
|
|
break;
|
|
default:
|
|
PRINTF_OUT("\?\?\?\n");
|
|
break;
|
|
}
|
|
PRINTF_OUT("program change: %s\n",ofp->progchange?"ON":"OFF");
|
|
PRINTF_OUT("pitch wheel range: %u\n",(u_int)ofp->pwheelrange);
|
|
i=((ofp->rs232brate10[1]<<8)+ofp->rs232brate10[0])*10;
|
|
PRINTF_OUT("RS232 baudrate: %u\n",i);
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
akai_cdsetup3000_info(struct file_s *fp)
|
|
{
|
|
char nbuf[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
u_char *buf;
|
|
struct akai_cdsetup3000_s *hp;
|
|
struct akai_cdsetup3000_entry_s *ep;
|
|
u_int enr;
|
|
u_int e,i;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* allocate buffer */
|
|
if (fp->size<sizeof(struct akai_cdsetup3000_s)){
|
|
PRINTF_ERR("invalid file size\n");
|
|
return -1;
|
|
}
|
|
if ((buf=(u_char *)malloc(fp->size))==NULL){
|
|
PRINTF_ERR("cannot allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* header */
|
|
hp=(struct akai_cdsetup3000_s *)buf;
|
|
/* marked file entries */
|
|
ep=(struct akai_cdsetup3000_entry_s *)(buf+sizeof(struct akai_cdsetup3000_s));
|
|
/* number of entries */
|
|
enr=(fp->size-sizeof(struct akai_cdsetup3000_s))/sizeof(struct akai_cdsetup3000_entry_s);
|
|
|
|
/* read file */
|
|
if (akai_read_file(0,buf,fp,0,fp->size)<0){
|
|
PRINTF_ERR("cannot read file\n");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
/* name */
|
|
akai2ascii_name(hp->name,nbuf,fp->volp->type==AKAI_VOL_TYPE_S900);
|
|
PRINTF_OUT("ramname: \"%s\"\n\n",nbuf);
|
|
|
|
/* CD-ROM label */
|
|
akai2ascii_name(hp->cdlabel,nbuf,fp->volp->type==AKAI_VOL_TYPE_S900);
|
|
PRINTF_OUT("CD-ROM label: \"%s\"\n",nbuf);
|
|
|
|
/* print marked file entries */
|
|
PRINTF_OUT("\nmarked files (part:vol/file):\n---------------------------------------------\n");
|
|
i=0;
|
|
for (e=0;e<enr;e++){
|
|
if (ep[e].parti!=0xff){ /* used entry? */
|
|
PRINTF_OUT("%c:%03u/%03u ",
|
|
'A'+ep[e].parti,
|
|
ep[e].voli+1,
|
|
(ep[e].filei[1]<<8)+ep[e].filei[0]+1);
|
|
if (i%4==3){
|
|
PRINTF_OUT("\n");
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
if (i%4!=0){
|
|
PRINTF_OUT("\n");
|
|
}
|
|
PRINTF_OUT("---------------------------------------------\n");
|
|
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/* fix RAM name of AKAI file */
|
|
int
|
|
akai_fixramname(struct file_s *fp)
|
|
{
|
|
static char nbuf[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
static u_char buf[sizeof(struct akai_genfilehdr_s)]; /* XXX enough for all cases */
|
|
u_char *np;
|
|
int s900flag;
|
|
|
|
if ((fp==NULL)||(fp->volp==NULL)||(fp->index>=fp->volp->fimax)){
|
|
return -1;
|
|
}
|
|
|
|
/* file type */
|
|
s900flag=0; /* default */
|
|
switch (fp->type){
|
|
case AKAI_SAMPLE900_FTYPE: /* S900 sample */
|
|
case AKAI_PROGRAM900_FTYPE: /* S900 program */
|
|
/* Note: name in S900 sample/program file header starts at byte 0 */
|
|
np=buf;
|
|
s900flag=1;
|
|
break;
|
|
case AKAI_SAMPLE1000_FTYPE: /* S1000 sample */
|
|
case AKAI_SAMPLE3000_FTYPE: /* S3000 sample */
|
|
case AKAI_CDSAMPLE3000_FTYPE: /* CD3000 CD-ROM sample parameters */
|
|
case AKAI_PROGRAM1000_FTYPE: /* S1000 program */
|
|
case AKAI_PROGRAM3000_FTYPE: /* S3000 program */
|
|
case AKAI_DRUM1000_FTYPE: /* S1000 or S3000 drum settings file */
|
|
case AKAI_FXFILE_FTYPE: /* S1100 or S3000 effects file */
|
|
case AKAI_QLFILE_FTYPE: /* S1100 or S3000 cue-list file */
|
|
case AKAI_TLFILE_FTYPE: /* S1100 or S3000 take-list file */
|
|
case AKAI_MULTI3000_FTYPE: /* S3000 multi file */
|
|
{
|
|
/* use generic file header */
|
|
struct akai_genfilehdr_s *p;
|
|
p=(struct akai_genfilehdr_s *)buf;
|
|
np=p->name;
|
|
}
|
|
break;
|
|
case AKAI_CDSETUP3000_FTYPE:
|
|
{
|
|
/* CD3000 CD-ROM setup file */
|
|
/* Note: generic file header does not apply for this file type! */
|
|
struct akai_cdsetup3000_s *p;
|
|
p=(struct akai_cdsetup3000_s *)buf;
|
|
np=p->name;
|
|
}
|
|
break;
|
|
default:
|
|
/* unknown or unsupported */
|
|
return 1; /* no error */
|
|
}
|
|
|
|
/* read header */
|
|
if (akai_read_file(0,buf,fp,0,sizeof(struct akai_genfilehdr_s))<0){
|
|
PRINTF_ERR("cannot read header\n");
|
|
return -1;
|
|
}
|
|
|
|
/* copy file name to name in RAM */
|
|
akai2ascii_name(fp->volp->file[fp->index].name,nbuf,fp->volp->type==AKAI_VOL_TYPE_S900);
|
|
ascii2akai_name(nbuf,np,s900flag);
|
|
|
|
/* write header */
|
|
if (akai_write_file(0,buf,fp,0,sizeof(struct akai_genfilehdr_s))<0){
|
|
PRINTF_ERR("cannot write header\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
};
|
|
|
|
|
|
|
|
int
|
|
akai_s900comprfile_updateuncompr(struct file_s *fp)
|
|
{
|
|
u_int osver;
|
|
|
|
if (fp==NULL){
|
|
return -1;
|
|
}
|
|
|
|
/* check if compressed file in S900 volume */
|
|
if ((fp->volp==NULL)||(fp->volp->type!=AKAI_VOL_TYPE_S900)||(fp->osver==0)){
|
|
return -1;
|
|
}
|
|
|
|
/* check if supported file type */
|
|
if (fp->type!=AKAI_SAMPLE900_FTYPE){
|
|
/* no error, keep osver */
|
|
return 0;
|
|
}
|
|
|
|
/* S900 sample file, compressed sample format */
|
|
/* non-compressed sample size in bytes */
|
|
osver=akai_sample900_getsamplesize(fp);
|
|
/* number of un-compressed floppy blocks */
|
|
/* Note: without sample header */
|
|
osver=(osver+AKAI_FL_BLOCKSIZE-1)/AKAI_FL_BLOCKSIZE; /* round up */
|
|
if (osver==0){ /* unsuitable osver? */
|
|
osver=1; /* XXX non zero */
|
|
}
|
|
|
|
/* set osver of file */
|
|
/* Note: akai_rename_file() will correct osver if necessary */
|
|
if (akai_rename_file(fp,NULL,fp->volp,AKAI_CREATE_FILE_NOINDEX,NULL,osver)<0){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
u_int
|
|
akai_sample900_getsamplesize(struct file_s *fp)
|
|
{
|
|
static struct akai_sample900_s s900hdr;
|
|
static u_int samplecount;
|
|
static u_int samplecountpart;
|
|
static u_int samplesize;
|
|
|
|
if (fp==NULL){
|
|
return 0;
|
|
}
|
|
if (fp->type!=(u_char)AKAI_SAMPLE900_FTYPE){ /* not S900 sample? */
|
|
return 0;
|
|
}
|
|
|
|
/* read header to memory */
|
|
if (akai_read_file(0,(u_char *)&s900hdr,fp,0,sizeof(struct akai_sample900_s))<0){
|
|
PRINTF_ERR("cannot read sample header\n");
|
|
return 0;
|
|
}
|
|
|
|
/* number of samples */
|
|
/* XXX should be an even number */
|
|
samplecount=(s900hdr.slen[3]<<24)
|
|
+(s900hdr.slen[2]<<16)
|
|
+(s900hdr.slen[1]<<8)
|
|
+s900hdr.slen[0];
|
|
/* number of samples per part */
|
|
samplecountpart=(samplecount+1)/2; /* round up */
|
|
/* size in bytes in S900 non-compressed sample format */
|
|
samplesize=3*samplecountpart;
|
|
return samplesize;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
akai_sample900noncompr_sample2wav(u_char *sbuf,u_char *wavbuf,u_int samplecountpart)
|
|
{
|
|
u_int i;
|
|
|
|
if ((sbuf==NULL)||(wavbuf==NULL)){
|
|
return;
|
|
}
|
|
if (samplecountpart==0){
|
|
return;
|
|
}
|
|
|
|
/* convert 12bit S900 non-compressed sample format into 16bit WAV sample format */
|
|
for (i=0;i<samplecountpart;i++){ /* first part */
|
|
wavbuf[i*2+1]=sbuf[i*2+1];
|
|
wavbuf[i*2+0]=0xf0&sbuf[i*2+0];
|
|
}
|
|
for (i=0;i<samplecountpart;i++){ /* second part */
|
|
wavbuf[samplecountpart*2+i*2+1]=sbuf[samplecountpart*2+i];
|
|
wavbuf[samplecountpart*2+i*2+0]=0xf0&(sbuf[i*2+0]<<4);
|
|
}
|
|
}
|
|
|
|
void
|
|
akai_sample900noncompr_wav2sample(u_char *sbuf,u_char *wavbuf,u_int samplecountpart)
|
|
{
|
|
u_int i;
|
|
|
|
if ((sbuf==NULL)||(wavbuf==NULL)){
|
|
return;
|
|
}
|
|
if (samplecountpart==0){
|
|
return;
|
|
}
|
|
|
|
/* convert 16bit WAV sample format into 12bit S900 non-compressed sample format */
|
|
for (i=0;i<samplecountpart;i++){ /* first part */
|
|
sbuf[i*2+1]=wavbuf[i*2+1];
|
|
sbuf[i*2+0]=0xf0&wavbuf[i*2+0];
|
|
}
|
|
for (i=0;i<samplecountpart;i++){ /* second part */
|
|
sbuf[samplecountpart*2+i]=wavbuf[samplecountpart*2+i*2+1];
|
|
sbuf[i*2+0]|=0x0f&(wavbuf[samplecountpart*2+i*2+0]>>4);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
u_int
|
|
akai_sample900compr_getbits(u_char *buf,u_int bitpos,u_int bitnum)
|
|
{
|
|
u_int bytepos;
|
|
u_char bmask;
|
|
u_int val;
|
|
u_int i;
|
|
|
|
if ((buf==NULL)||(bitnum==0)){
|
|
return 0;
|
|
}
|
|
/* XXX no check if bitnum too large for u_int */
|
|
/* XXX no check if bitpos+bitnum too large for buf */
|
|
|
|
val=0;
|
|
for (i=0;i<bitnum;i++,bitpos++){
|
|
bytepos=(bitpos>>3); /* /8: 8 bits per byte */
|
|
bmask=(1<<(7-(7&bitpos))); /* Note: upper bit first */
|
|
val<<=1;
|
|
if ((bmask&buf[bytepos])!=0){
|
|
val|=1;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
u_int
|
|
akai_sample900compr_sample2wav(u_char *sbuf,u_char *wavbuf,u_int sbufsiz,u_int wavbufsiz)
|
|
{
|
|
u_char upbitnum;
|
|
u_char upsign;
|
|
u_short upabsval;
|
|
short curval;
|
|
short curinc;
|
|
u_int bitremain;
|
|
u_int bitpos;
|
|
u_int wavpos;
|
|
u_char code;
|
|
u_int i,j;
|
|
|
|
if ((sbuf==NULL)||(wavbuf==NULL)){
|
|
return 0;
|
|
}
|
|
if ((sbufsiz==0)||(wavbufsiz==0)){
|
|
return 0;
|
|
}
|
|
|
|
/* convert S900 compressed sample format into 16bit WAV sample format */
|
|
curval=0;
|
|
curinc=0;
|
|
bitremain=sbufsiz*8; /* 8 bits per byte */
|
|
bitpos=0;
|
|
wavpos=0;
|
|
for (;(bitremain>0)&&(wavpos+1<wavbufsiz);){
|
|
/* get code nibble */
|
|
if (bitremain<4){
|
|
break; /* end */
|
|
}
|
|
code=(u_char)akai_sample900compr_getbits(sbuf,bitpos,4);
|
|
#ifdef SAMPLE900COMPR_DEBUG
|
|
PRINTF_OUT("%08x: code=%x\n",bitpos,code);
|
|
#endif
|
|
bitpos+=4;
|
|
bitremain-=4;
|
|
/* parse code */
|
|
if (code==0x0){
|
|
/* Note: no further bits for this group */
|
|
/* generate signal */
|
|
for (i=0;(i<SAMPLE900COMPR_GROUP_SAMPNUM)&&(wavpos+1<wavbufsiz);i++){
|
|
/* update curval */
|
|
curval+=curinc;
|
|
/* convert 12bit sample into 16bit WAV sample */
|
|
wavbuf[wavpos++]=0xf0&(u_char)(curval<<4);
|
|
wavbuf[wavpos++]=0xff&(u_char)(curval>>4);
|
|
}
|
|
}else{
|
|
/* number of bits for upabsval */
|
|
upbitnum=SAMPLE900COMPR_UPBITNUM_NEGCODE_OFF-code;
|
|
/* Note: upbitnum>SAMPLE900COMPR_UPBITNUM_MAX is supported here, but should not occur normally */
|
|
#ifdef SAMPLE900COMPR_DEBUG
|
|
if (upbitnum>SAMPLE900COMPR_UPBITNUM_MAX){
|
|
PRINTF_OUT(" upbitnum>SAMPLE900COMPR_UPBITNUM_MAX\n");
|
|
}
|
|
#endif
|
|
/* number of required remaining bits for instruction code */
|
|
j=SAMPLE900COMPR_GROUP_SAMPNUM*(1+((u_int)upbitnum)); /* Note: per word: 1 sign flag bit and n bits */
|
|
if (bitremain<j){
|
|
break; /* end */
|
|
}
|
|
/* generate signal */
|
|
for (i=0;(i<SAMPLE900COMPR_GROUP_SAMPNUM)&&(wavpos+1<wavbufsiz);i++){
|
|
/* get sign flag bit */
|
|
upsign=(u_char)akai_sample900compr_getbits(sbuf,bitpos+0+i,1);
|
|
/* get value word */
|
|
upabsval=(u_short)akai_sample900compr_getbits(sbuf,bitpos+SAMPLE900COMPR_GROUP_SAMPNUM+i*((u_int)upbitnum),(u_int)upbitnum);
|
|
#ifdef SAMPLE900COMPR_DEBUG
|
|
PRINTF_OUT(" %c%u\n",(upsign==0)?'+':'-',(u_int)upabsval);
|
|
#endif
|
|
/* update curinc */
|
|
if (upsign==0){
|
|
/* plus */
|
|
curinc+=(short)upabsval;
|
|
}else{
|
|
/* minus */
|
|
curinc-=(short)upabsval;
|
|
}
|
|
/* update curval */
|
|
curval+=curinc;
|
|
/* Note: SAMPLE900COMPR_BITMASK&curval contains sample value */
|
|
/* convert 12bit sample into 16bit WAV sample */
|
|
wavbuf[wavpos++]=0xf0&(u_char)(curval<<4);
|
|
wavbuf[wavpos++]=0xff&(u_char)(curval>>4);
|
|
}
|
|
bitpos+=j;
|
|
bitremain-=j;
|
|
}
|
|
}
|
|
|
|
return wavpos;
|
|
}
|
|
|
|
void
|
|
akai_sample900compr_setbits(u_char *buf,u_int bitpos,u_int bitnum,u_int val)
|
|
{
|
|
u_int bytepos;
|
|
u_char bmask;
|
|
u_int i;
|
|
|
|
if ((buf==NULL)||(bitnum==0)){
|
|
return;
|
|
}
|
|
/* XXX no check if bitnum too large for u_int */
|
|
/* XXX no check if bitpos+bitnum too large for buf */
|
|
|
|
for (i=0;i<bitnum;i++,bitpos++){
|
|
bytepos=(bitpos>>3); /* /8: 8 bits per byte */
|
|
bmask=(1<<(7-(7&bitpos))); /* Note: upper bit first */
|
|
if (((1<<(bitnum-1-i))&val)!=0){ /* bit set? (Note: upper bit first) */
|
|
/* set bit */
|
|
buf[bytepos]|=bmask;
|
|
}else{
|
|
/* clear bit */
|
|
buf[bytepos]&=~bmask;
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
akai_sample900compr_wav2sample(u_char *sbuf,u_char *wavbuf,u_int samplecountpart)
|
|
{
|
|
/* must be static for multiple calls, must be initialized */
|
|
static u_char *upbitnumbuf=NULL;
|
|
static u_int *upsignbuf=NULL;
|
|
static u_short *upabsvalbuf=NULL;
|
|
static u_int groupcount=0;
|
|
|
|
short sval;
|
|
short curval;
|
|
short curinc;
|
|
short upval;
|
|
u_short upabsval;
|
|
u_char upbitnum;
|
|
u_int upsign;
|
|
u_int bitpos;
|
|
u_char code;
|
|
u_int g,s,i,j;
|
|
int ret;
|
|
|
|
if ((sbuf==NULL)&&(wavbuf==NULL)){
|
|
ret=0; /* no error */
|
|
/* free buffers if still allocated */
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
|
|
ret=-1; /* no success so far */
|
|
|
|
/* convert 16bit WAV sample format into S900 compressed sample format */
|
|
|
|
if (sbuf==NULL){
|
|
/* first pass */
|
|
|
|
/* free buffers if still allocated */
|
|
if (upbitnumbuf!=NULL){
|
|
free(upbitnumbuf);
|
|
upbitnumbuf=NULL;
|
|
}
|
|
if (upsignbuf!=NULL){
|
|
free(upsignbuf);
|
|
upsignbuf=NULL;
|
|
}
|
|
if (upabsvalbuf!=NULL){
|
|
free(upabsvalbuf);
|
|
upabsvalbuf=NULL;
|
|
}
|
|
|
|
/* number of groups */
|
|
/* Note: 2*samplecountpart+1 to encode at least one additional zero sample behind end */
|
|
groupcount=(2*samplecountpart+1+SAMPLE900COMPR_GROUP_SAMPNUM-1)/SAMPLE900COMPR_GROUP_SAMPNUM; /* round up */
|
|
|
|
/* allocate buffers */
|
|
upbitnumbuf=(u_char *)malloc(groupcount*sizeof(u_char));
|
|
if (upbitnumbuf==NULL){
|
|
PERROR("cannot allocate upbitnumbuf");
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
upsignbuf=(u_int *)malloc(groupcount*sizeof(u_int));
|
|
if (upsignbuf==NULL){
|
|
PERROR("cannot allocate upsignbuf");
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
upabsvalbuf=(u_short *)malloc(groupcount*SAMPLE900COMPR_GROUP_SAMPNUM*sizeof(u_short));
|
|
if (upabsvalbuf==NULL){
|
|
PERROR("cannot allocate upabsvalbuf");
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
|
|
/* gather groups */
|
|
curval=0;
|
|
curinc=0;
|
|
sval=0;
|
|
for (g=0,s=0;g<groupcount;g++){
|
|
upbitnum=0;
|
|
upsign=0;
|
|
/* samples within group */
|
|
for (i=0;i<SAMPLE900COMPR_GROUP_SAMPNUM;i++,s++){
|
|
if (s<2*samplecountpart){
|
|
/* get 12bit sample from 16bit WAV sample */
|
|
sval=(((short)(char)wavbuf[s*2+1])<<4)+(((short)(u_char)wavbuf[s*2+0])>>4);
|
|
}else{
|
|
/* encode zero sample behind end */
|
|
sval=0;
|
|
}
|
|
|
|
/* determine required upsign,upabsval */
|
|
upsign<<=1;
|
|
upval=sval-(curval+curinc);
|
|
/* choose optimum interval position for min. abs. value */
|
|
while (upval>SAMPLE900COMPR_INTERVALSIZ2){
|
|
upval-=SAMPLE900COMPR_INTERVALSIZ;
|
|
}
|
|
while (upval<-SAMPLE900COMPR_INTERVALSIZ2){
|
|
upval+=SAMPLE900COMPR_INTERVALSIZ;
|
|
}
|
|
/* Note: max./min. possible value for resulting upval is +/-SAMPLE900COMPR_INTERVALSIZ2 */
|
|
/* which requires SAMPLE900COMPR_UPBITNUM_MAX bits for upabsval */
|
|
if (upval>=0){
|
|
/* plus */
|
|
/* upsign|=0; */
|
|
upabsval=SAMPLE900COMPR_BITMASK&(u_short)upval;
|
|
/* update curinc */
|
|
curinc+=(short)upabsval;
|
|
}else{
|
|
/* minus */
|
|
upsign|=1;
|
|
upabsval=SAMPLE900COMPR_BITMASK&(u_short)(-upval);
|
|
/* update curinc */
|
|
curinc-=(short)upabsval;
|
|
}
|
|
upabsvalbuf[s]=upabsval;
|
|
|
|
/* determine max. number of required bits for upabsval in group */
|
|
/* start with previous upbitnum */
|
|
for (j=(u_int)upbitnum;j<SAMPLE900COMPR_UPBITNUM_MAX;j++){
|
|
if (((1<<j)&upabsval)!=0){ /* bit j set? */
|
|
upbitnum=(u_char)(j+1);
|
|
}
|
|
}
|
|
|
|
/* update curval */
|
|
curval+=curinc;
|
|
/* Note: SAMPLE900COMPR_BITMASK&curval contains sample value */
|
|
if ((SAMPLE900COMPR_BITMASK&(curval-sval))!=0){
|
|
/* XXX should not happen */
|
|
PRINTF_ERR("%06x,%02x: error: sval=%i curval=%i\n",g,i,sval,curval);
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
}
|
|
#ifdef SAMPLE900COMPR_DEBUG
|
|
PRINTF_OUT("%06x: upbitnum=%2u upsign=%04x\n",g,(u_int)upbitnum,upsign);
|
|
#endif
|
|
upbitnumbuf[g]=upbitnum;
|
|
upsignbuf[g]=upsign;
|
|
}
|
|
|
|
/* determine number of bits required in sbuf for second pass */
|
|
bitpos=0;
|
|
for (g=0;g<groupcount;g++){
|
|
/* see "encode groups" below */
|
|
bitpos+=4;
|
|
if (upbitnumbuf[g]!=0){
|
|
bitpos+=SAMPLE900COMPR_GROUP_SAMPNUM*(1+((u_int)upbitnumbuf[g]));
|
|
}
|
|
}
|
|
bitpos+=(7&(8-(7&bitpos))); /* number of bits missing to full byte */
|
|
|
|
ret=(int)(bitpos>>3); /* success, return number of required bytes in sbuf for second pass */
|
|
/* keep buffers for second pass */
|
|
goto akai_sample900compr_wav2sample_keepbufexit;
|
|
}else{
|
|
/* second pass */
|
|
|
|
if (wavbuf==NULL){
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
|
|
/* check allocation of buffers */
|
|
if ((upbitnumbuf==NULL)||(upsignbuf==NULL)||(upabsvalbuf==NULL)){
|
|
PRINTF_ERR("error: buffers not allocated in second pass\n");
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
|
|
/* XXX ignore samplecountpart in second pass */
|
|
|
|
/* encode groups */
|
|
bitpos=0;
|
|
for (g=0,s=0;g<groupcount;g++){
|
|
/* determine code nibble */
|
|
upbitnum=upbitnumbuf[g];
|
|
if (upbitnum==0){
|
|
code=0x0;
|
|
}else{
|
|
code=SAMPLE900COMPR_UPBITNUM_NEGCODE_OFF-upbitnum;
|
|
}
|
|
#ifdef SAMPLE900COMPR_DEBUG
|
|
PRINTF_OUT("%08x: code=%x\n",bitpos,code);
|
|
#endif
|
|
/* save code nibble */
|
|
akai_sample900compr_setbits(sbuf,bitpos,4,(u_int)code);
|
|
bitpos+=4;
|
|
|
|
if (upbitnum==0){
|
|
s+=SAMPLE900COMPR_GROUP_SAMPNUM; /* advance in upabsvalbuf[] */
|
|
/* no further bits to save for this group */
|
|
}else{
|
|
/* save upsign */
|
|
upsign=upsignbuf[g];
|
|
akai_sample900compr_setbits(sbuf,bitpos,SAMPLE900COMPR_GROUP_SAMPNUM,upsign);
|
|
bitpos+=SAMPLE900COMPR_GROUP_SAMPNUM;
|
|
/* samples within group */
|
|
for (i=0;i<SAMPLE900COMPR_GROUP_SAMPNUM;i++,s++){
|
|
/* save upabsval */
|
|
upabsval=upabsvalbuf[s];
|
|
akai_sample900compr_setbits(sbuf,bitpos,(u_int)upbitnum,(u_int)upabsval);
|
|
bitpos+=(u_int)upbitnum;
|
|
#ifdef SAMPLE900COMPR_DEBUG
|
|
PRINTF_OUT(" %c%u\n",
|
|
(((1<<(SAMPLE900COMPR_GROUP_SAMPNUM-1-i))&upsign)==0)?'+':'-',(u_int)upabsval); /* Note: upper bit first */
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
j=(7&(8-(7&bitpos))); /* number of bits missing to full byte */
|
|
if (j!=0){
|
|
/* zero padding to full byte */
|
|
akai_sample900compr_setbits(sbuf,bitpos,j,0);
|
|
bitpos+=j;
|
|
}
|
|
|
|
ret=(int)(bitpos>>3); /* success, return number of used bytes in sbuf */
|
|
/* free buffers */
|
|
goto akai_sample900compr_wav2sample_freebufexit;
|
|
}
|
|
|
|
akai_sample900compr_wav2sample_freebufexit:
|
|
if (upbitnumbuf!=NULL){
|
|
free(upbitnumbuf);
|
|
upbitnumbuf=NULL;
|
|
}
|
|
if (upsignbuf!=NULL){
|
|
free(upsignbuf);
|
|
upsignbuf=NULL;
|
|
}
|
|
if (upabsvalbuf!=NULL){
|
|
free(upabsvalbuf);
|
|
upabsvalbuf=NULL;
|
|
}
|
|
|
|
akai_sample900compr_wav2sample_keepbufexit:
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
akai_sample900_compr2noncompr(struct file_s *fp,struct vol_s *volp)
|
|
{
|
|
struct file_s tmpfile;
|
|
struct akai_sample900_s s900hdr;
|
|
u_int samplecount;
|
|
u_int samplecountpart;
|
|
u_int samplesizecompr;
|
|
u_char *sbufcompr;
|
|
u_int samplesizenoncompr;
|
|
u_char *sbufnoncompr;
|
|
u_int wavsamplesize;
|
|
u_char *wavbuf;
|
|
static char fname[AKAI_NAME_LEN_S900+3+1]; /* name (ASCII), +3 for ".S9", +1 for '\0' */
|
|
int replaceflag;
|
|
u_int findex;
|
|
u_int i;
|
|
int ret;
|
|
|
|
if (fp==NULL){
|
|
return -1;
|
|
}
|
|
|
|
if (volp==NULL){
|
|
/* destination volume same as source volume */
|
|
volp=fp->volp;
|
|
replaceflag=1; /* replace file */
|
|
}else{
|
|
replaceflag=0; /* keep source file */
|
|
}
|
|
if ((volp==NULL)||(volp->partp==NULL)){
|
|
return -1;
|
|
}
|
|
|
|
/* file type */
|
|
if ((fp->type!=(u_char)AKAI_SAMPLE900_FTYPE)||(fp->osver==0)){ /* not S900 compressed sample file? */
|
|
PRINTF_ERR("not an S900 compressed sample file\n");
|
|
return -1;
|
|
}
|
|
if (fp->size<sizeof(struct akai_sample900_s)){
|
|
PRINTF_ERR("invalid sample size\n");
|
|
return -1;
|
|
}
|
|
|
|
sbufcompr=NULL; /* no sample so far */
|
|
sbufnoncompr=NULL; /* no sample so far */
|
|
wavbuf=NULL; /* no sample so far */
|
|
ret=-1; /* no success so far */
|
|
|
|
/* read header to memory */
|
|
if (akai_read_file(0,(u_char *)&s900hdr,fp,0,sizeof(struct akai_sample900_s))<0){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* number of samples */
|
|
/* XXX should be an even number */
|
|
samplecount=(s900hdr.slen[3]<<24)
|
|
+(s900hdr.slen[2]<<16)
|
|
+(s900hdr.slen[1]<<8)
|
|
+s900hdr.slen[0];
|
|
/* number of samples per part */
|
|
samplecountpart=(samplecount+1)/2; /* round up */
|
|
/* size in bytes in S900 non-compressed sample format */
|
|
samplesizenoncompr=3*samplecountpart;
|
|
/* WAV size in bytes */
|
|
wavsamplesize=2*samplecountpart*2; /* *2 for 16bit per WAV sample word */
|
|
/* S900 compressed sample size */
|
|
samplesizecompr=fp->size-sizeof(struct akai_sample900_s);
|
|
|
|
/* create non-compressed sample file name */
|
|
/* Note: use RAM name as basis (-> akai_fixramname() not needed afterwards) */
|
|
akai2ascii_name((u_char *)s900hdr.name,fname,1); /* 1: S900 */
|
|
strcat(fname,".S9");
|
|
|
|
/* check if destination file already exists */
|
|
if (akai_find_file(volp,&tmpfile,fname)==0){
|
|
/* exists */
|
|
PRINTF_ERR("destination file name \"%s\" already used\n",fname);
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* check if enough free blocks */
|
|
/* required size of non-compressed file in blocks */
|
|
i=(sizeof(struct akai_sample900_s)+samplesizenoncompr+volp->partp->blksize-1)/volp->partp->blksize;
|
|
if (replaceflag){
|
|
if (samplesizecompr<samplesizenoncompr){
|
|
/* subtract size of existing compressed file in blocks */
|
|
i-=(sizeof(struct akai_sample900_s)+samplesizecompr+volp->partp->blksize-1)/volp->partp->blksize;
|
|
}else{
|
|
i=0;
|
|
}
|
|
}
|
|
if (volp->partp->bfree<i){
|
|
/* not enough space left */
|
|
PRINTF_ERR("not enough space left for destination file \"%s\"\n",fname);
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* allocate compressed sample buffer */
|
|
sbufcompr=(u_char *)malloc(samplesizecompr);
|
|
if (sbufcompr==NULL){
|
|
PRINTF_ERR("cannot allocate compressed sample buffer\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* allocate non-compressed sample buffer */
|
|
sbufnoncompr=(u_char *)malloc(samplesizenoncompr);
|
|
if (sbufnoncompr==NULL){
|
|
PRINTF_ERR("cannot allocate non-compressed sample buffer\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* allocate WAV sample buffer */
|
|
wavbuf=(u_char *)malloc(wavsamplesize);
|
|
if (wavbuf==NULL){
|
|
PRINTF_ERR("cannot allocate WAV buffer\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* read compressed sample to memory */
|
|
if (akai_read_file(0,sbufcompr,fp,sizeof(struct akai_sample900_s),sizeof(struct akai_sample900_s)+samplesizecompr)<0){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* convert S900 compressed sample format into 16bit WAV sample format */
|
|
i=akai_sample900compr_sample2wav(sbufcompr,wavbuf,samplesizecompr,wavsamplesize);
|
|
if (i<wavsamplesize){
|
|
PRINTF_ERR("warning: incomplete sample data\n");
|
|
/* zero padding */
|
|
bzero(wavbuf+i,wavsamplesize-i);
|
|
}
|
|
|
|
/* convert 16bit WAV sample format into S900 non-compressed sample format */
|
|
akai_sample900noncompr_wav2sample(sbufnoncompr,wavbuf,samplecountpart);
|
|
|
|
if (replaceflag){
|
|
/* keep file index */
|
|
findex=fp->index;
|
|
/* delete source file */
|
|
if (akai_delete_file(fp)<0){
|
|
PRINTF_ERR("cannot overwrite existing file\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
}else{
|
|
findex=AKAI_CREATE_FILE_NOINDEX;
|
|
}
|
|
/* create file */
|
|
/* Note: akai_create_file() will correct osver if necessary */
|
|
if (akai_create_file(volp,&tmpfile,
|
|
sizeof(struct akai_sample900_s)+samplesizenoncompr,
|
|
findex,
|
|
fname,
|
|
0, /* non-compressed */
|
|
NULL)<0){
|
|
PRINTF_ERR("cannot create file\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* write sample header */
|
|
if (akai_write_file(0,(u_char *)&s900hdr,&tmpfile,0,sizeof(struct akai_sample900_s))<0){
|
|
PRINTF_ERR("cannot write sample header\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
/* write non-compressed sample */
|
|
if (akai_write_file(0,sbufnoncompr,&tmpfile,sizeof(struct akai_sample900_s),sizeof(struct akai_sample900_s)+samplesizenoncompr)<0){
|
|
PRINTF_ERR("cannot write sample\n");
|
|
goto akai_sample900_compr2noncompr_exit;
|
|
}
|
|
|
|
ret=0; /* success */
|
|
|
|
akai_sample900_compr2noncompr_exit:
|
|
if (sbufcompr!=NULL){
|
|
free(sbufcompr);
|
|
}
|
|
if (sbufnoncompr!=NULL){
|
|
free(sbufnoncompr);
|
|
}
|
|
if (wavbuf!=NULL){
|
|
free(wavbuf);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
akai_sample900_noncompr2compr(struct file_s *fp,struct vol_s *volp)
|
|
{
|
|
struct file_s tmpfile;
|
|
struct akai_sample900_s s900hdr;
|
|
u_int samplecount;
|
|
u_int samplecountpart;
|
|
u_int samplesizecompr;
|
|
u_char *sbufcompr;
|
|
u_int samplesizenoncompr;
|
|
u_char *sbufnoncompr;
|
|
u_int wavsamplesize;
|
|
u_char *wavbuf;
|
|
static char fname[AKAI_NAME_LEN_S900+4+1]; /* name (ASCII), +4 for ".S9C", +1 for '\0' */
|
|
int replaceflag;
|
|
u_int findex;
|
|
u_int osver;
|
|
u_int i;
|
|
int r;
|
|
int ret;
|
|
|
|
if (fp==NULL){
|
|
return -1;
|
|
}
|
|
|
|
if (volp==NULL){
|
|
/* destination volume same as source volume */
|
|
volp=fp->volp;
|
|
replaceflag=1; /* replace file */
|
|
}else{
|
|
replaceflag=0; /* keep source file */
|
|
}
|
|
if ((volp==NULL)||(volp->partp==NULL)){
|
|
return -1;
|
|
}
|
|
|
|
/* file type */
|
|
if ((fp->type!=(u_char)AKAI_SAMPLE900_FTYPE)||(fp->osver!=0)){ /* not S900 non-compressed sample file? */
|
|
PRINTF_ERR("not an S900 non-compressed sample file\n");
|
|
return -1;
|
|
}
|
|
if (fp->size<sizeof(struct akai_sample900_s)){
|
|
PRINTF_ERR("invalid sample size\n");
|
|
return -1;
|
|
}
|
|
|
|
sbufcompr=NULL; /* no sample so far */
|
|
sbufnoncompr=NULL; /* no sample so far */
|
|
wavbuf=NULL; /* no sample so far */
|
|
ret=-1; /* no success so far */
|
|
|
|
/* read header to memory */
|
|
if (akai_read_file(0,(u_char *)&s900hdr,fp,0,sizeof(struct akai_sample900_s))<0){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* number of samples */
|
|
/* XXX should be an even number */
|
|
samplecount=(s900hdr.slen[3]<<24)
|
|
+(s900hdr.slen[2]<<16)
|
|
+(s900hdr.slen[1]<<8)
|
|
+s900hdr.slen[0];
|
|
/* number of samples per part */
|
|
samplecountpart=(samplecount+1)/2; /* round up */
|
|
/* size in bytes in S900 non-compressed sample format */
|
|
samplesizenoncompr=3*samplecountpart;
|
|
/* WAV size in bytes */
|
|
wavsamplesize=2*samplecountpart*2; /* *2 for 16bit per WAV sample word */
|
|
|
|
/* allocate non-compressed sample buffer */
|
|
sbufnoncompr=(u_char *)malloc(samplesizenoncompr);
|
|
if (sbufnoncompr==NULL){
|
|
PRINTF_ERR("cannot allocate non-compressed sample buffer\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* allocate WAV sample buffer */
|
|
wavbuf=(u_char *)malloc(wavsamplesize);
|
|
if (wavbuf==NULL){
|
|
PRINTF_ERR("cannot allocate WAV buffer\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* read non-compressed sample to memory */
|
|
if (akai_read_file(0,sbufnoncompr,fp,sizeof(struct akai_sample900_s),sizeof(struct akai_sample900_s)+samplesizenoncompr)<0){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* convert S900 non-compressed sample format into 16bit WAV sample format */
|
|
akai_sample900noncompr_sample2wav(sbufnoncompr,wavbuf,samplecountpart);
|
|
|
|
/* first pass to convert 16bit WAV sample format into S900 compressed sample format */
|
|
/* Note: first pass of akai_sample900compr_wav2sample() requires WAV sample to be loaded to wavbuf */
|
|
r=akai_sample900compr_wav2sample(NULL,wavbuf,samplecountpart); /* NULL: first pass */
|
|
if (r<0){
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
/* S900 compressed sample size in bytes */
|
|
samplesizecompr=(u_int)r;
|
|
|
|
/* create compressed sample file name */
|
|
/* Note: use RAM name as basis (-> akai_fixramname() not needed afterwards) */
|
|
akai2ascii_name((u_char *)s900hdr.name,fname,1); /* 1: S900 */
|
|
strcat(fname,".S9C");
|
|
|
|
/* check if destination file already exists */
|
|
if (akai_find_file(volp,&tmpfile,fname)==0){
|
|
/* exists */
|
|
PRINTF_ERR("destination file name \"%s\" already used\n",fname);
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* check if enough free blocks */
|
|
/* required size of compressed file in blocks */
|
|
i=(sizeof(struct akai_sample900_s)+samplesizecompr+volp->partp->blksize-1)/volp->partp->blksize;
|
|
if (replaceflag){
|
|
if (samplesizenoncompr<samplesizecompr){
|
|
/* subtract size of existing non-compressed file in blocks */
|
|
i-=(sizeof(struct akai_sample900_s)+samplesizenoncompr+volp->partp->blksize-1)/volp->partp->blksize;
|
|
}else{
|
|
i=0;
|
|
}
|
|
}
|
|
if (volp->partp->bfree<i){
|
|
/* not enough space left */
|
|
PRINTF_ERR("not enough space left for destination file \"%s\"\n",fname);
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* allocate compressed sample buffer */
|
|
sbufcompr=(u_char *)malloc(samplesizecompr);
|
|
if (sbufcompr==NULL){
|
|
PRINTF_ERR("cannot allocate compressed sample buffer\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* second pass to convert 16bit WAV sample format into S900 compressed sample format */
|
|
if (akai_sample900compr_wav2sample(sbufcompr,wavbuf,samplecountpart)<0){ /* sbufcompr!=NULL: second pass */
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
if (replaceflag){
|
|
/* keep file index */
|
|
findex=fp->index;
|
|
/* delete source file */
|
|
if (akai_delete_file(fp)<0){
|
|
PRINTF_ERR("cannot overwrite existing file\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
}else{
|
|
findex=AKAI_CREATE_FILE_NOINDEX;
|
|
}
|
|
/* osver for S900 compressed sample file: number of un-compressed floppy blocks */
|
|
/* Note: without sample header */
|
|
osver=(samplesizenoncompr+AKAI_FL_BLOCKSIZE-1)/AKAI_FL_BLOCKSIZE; /* round up */
|
|
if (osver==0){ /* unsuitable osver? */
|
|
osver=1; /* XXX non zero */
|
|
}
|
|
/* create file */
|
|
/* Note: akai_create_file() will correct osver if necessary */
|
|
if (akai_create_file(volp,&tmpfile,
|
|
sizeof(struct akai_sample900_s)+samplesizecompr,
|
|
findex,
|
|
fname,
|
|
osver,
|
|
NULL)<0){
|
|
PRINTF_ERR("cannot create file\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* write sample header */
|
|
if (akai_write_file(0,(u_char *)&s900hdr,&tmpfile,0,sizeof(struct akai_sample900_s))<0){
|
|
PRINTF_ERR("cannot write sample header\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
/* write compressed sample */
|
|
if (akai_write_file(0,sbufcompr,&tmpfile,sizeof(struct akai_sample900_s),sizeof(struct akai_sample900_s)+samplesizecompr)<0){
|
|
PRINTF_ERR("cannot write sample\n");
|
|
goto akai_sample900_noncompr2compr_exit;
|
|
}
|
|
|
|
ret=0; /* success */
|
|
|
|
akai_sample900_noncompr2compr_exit:
|
|
if (sbufcompr!=NULL){
|
|
free(sbufcompr);
|
|
}
|
|
if (sbufnoncompr!=NULL){
|
|
free(sbufnoncompr);
|
|
}
|
|
if (wavbuf!=NULL){
|
|
free(wavbuf);
|
|
}
|
|
akai_sample900compr_wav2sample(NULL,NULL,0); /* NULL,NULL: free buffers if still allocated */
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
akai_sample2wav(struct file_s *fp,int wavfd,u_int *sizep,char **wavnamep,int what)
|
|
{
|
|
/* Note: static for multiple calls with different what */
|
|
static struct akai_sample3000_s s3000hdr;
|
|
static struct akai_sample900_s *s900hdrp;
|
|
static u_int hdrsize;
|
|
static u_int samplecount;
|
|
static u_int samplecountpart;
|
|
static u_int samplesize;
|
|
static u_int samplerate;
|
|
static u_char *sbuf;
|
|
static u_int wavsamplesize;
|
|
static u_char *wavbuf;
|
|
static int ret;
|
|
static char wavname[AKAI_NAME_LEN+4+1]; /* name (ASCII), +4 for ".<type>", +1 for '\0' */
|
|
static u_int nlen;
|
|
static u_int i;
|
|
|
|
if (fp==NULL){
|
|
return -1;
|
|
}
|
|
|
|
sbuf=NULL; /* no sample so far */
|
|
wavbuf=NULL; /* no sample so far */
|
|
ret=-1; /* no success so far */
|
|
|
|
if (what&SAMPLE2WAV_CHECK){
|
|
|
|
/* file type */
|
|
if (fp->type==(u_char)AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
hdrsize=sizeof(struct akai_sample900_s);
|
|
}else if (fp->type==(u_char)AKAI_SAMPLE1000_FTYPE){
|
|
/* S1000 sample */
|
|
hdrsize=sizeof(struct akai_sample1000_s);
|
|
}else if (fp->type==(u_char)AKAI_SAMPLE3000_FTYPE){
|
|
/* S3000 sample */
|
|
hdrsize=sizeof(struct akai_sample3000_s);
|
|
}else{
|
|
/* unknown or unsupported */
|
|
return 1; /* no error */
|
|
}
|
|
|
|
/* read header to memory */
|
|
/* Note: use S3000 header as buffer for S900 header */
|
|
if (akai_read_file(0,(u_char *)&s3000hdr,fp,0,hdrsize)<0){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
|
|
/* parse header */
|
|
if (fp->type==(u_char)AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
s900hdrp=(struct akai_sample900_s *)&s3000hdr;
|
|
/* number of samples */
|
|
/* XXX should be an even number */
|
|
samplecount=(s900hdrp->slen[3]<<24)
|
|
+(s900hdrp->slen[2]<<16)
|
|
+(s900hdrp->slen[1]<<8)
|
|
+s900hdrp->slen[0];
|
|
/* number of samples per part */
|
|
samplecountpart=(samplecount+1)/2; /* round up */
|
|
samplecount=2*samplecountpart; /* XXX correct samplecount */
|
|
if (fp->osver==0){
|
|
/* S900 non-compressed sample format */
|
|
/* size in bytes */
|
|
samplesize=3*samplecountpart;
|
|
}else{
|
|
/* S900 compressed sample format */
|
|
/* size in bytes */
|
|
if (fp->size<hdrsize){
|
|
PRINTF_ERR("invalid sample size\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
samplesize=fp->size-hdrsize;
|
|
}
|
|
samplerate=(s900hdrp->srate[1]<<8)
|
|
+s900hdrp->srate[0];
|
|
}else{
|
|
/* S1000/S3000 sample */
|
|
/* Note: S1000 header is contained within S3000 header */
|
|
/* number of samples */
|
|
samplecount=(s3000hdr.s1000.slen[3]<<24)
|
|
+(s3000hdr.s1000.slen[2]<<16)
|
|
+(s3000hdr.s1000.slen[1]<<8)
|
|
+s3000hdr.s1000.slen[0];
|
|
/* size in bytes */
|
|
samplesize=samplecount*2; /* *2 for 16bit per sample word */
|
|
samplecountpart=0;
|
|
samplerate=(s3000hdr.s1000.srate[1]<<8)
|
|
+s3000hdr.s1000.srate[0];
|
|
}
|
|
/* size in bytes */
|
|
wavsamplesize=samplecount*2; /* *2 for 16bit per WAV sample word */
|
|
/* Note: wavsamplesize==0 is allowed here */
|
|
|
|
#ifdef DEBUG
|
|
PRINTF_OUT("type: %15i\n",fp->type);
|
|
PRINTF_OUT("samplecount: %15u\n",samplecount);
|
|
PRINTF_OUT("samplesize: %15u bytes\n",samplesize);
|
|
PRINTF_OUT("samplerate: %15u Hz\n",samplerate);
|
|
#endif
|
|
|
|
/* check size */
|
|
if (hdrsize+samplesize>fp->size){
|
|
PRINTF_ERR("invalid sample size\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
|
|
if (sizep!=NULL){
|
|
/* WAV file size */
|
|
*sizep=WAV_HEAD_SIZE+wavsamplesize;
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
*sizep+=sizeof(struct wav_chunkhead_s)+hdrsize; /* sample header chunk (see below) */
|
|
#endif
|
|
}
|
|
|
|
/* create WAV name */
|
|
if ((fp->volp!=NULL)&&(fp->index<fp->volp->fimax)){
|
|
akai2ascii_name(fp->volp->file[fp->index].name,wavname,fp->volp->type==AKAI_VOL_TYPE_S900);
|
|
nlen=(u_int)strlen(wavname);
|
|
}else{
|
|
nlen=0;
|
|
}
|
|
bcopy(".wav",wavname+nlen,5);
|
|
|
|
if (wavnamep!=NULL){
|
|
/* pointer to name (wavname must be static!) */
|
|
*wavnamep=wavname;
|
|
}
|
|
}
|
|
|
|
if (what&SAMPLE2WAV_EXPORT){
|
|
|
|
if (wavsamplesize>0){
|
|
/* allocate WAV sample buffer */
|
|
wavbuf=(u_char *)malloc(wavsamplesize);
|
|
if (wavbuf==NULL){
|
|
PRINTF_ERR("cannot allocate WAV buffer\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
|
|
if (fp->type==(u_char)AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
/* allocate sample buffer */
|
|
sbuf=(u_char *)malloc(samplesize);
|
|
if (sbuf==NULL){
|
|
PRINTF_ERR("cannot allocate sample buffer\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
}else{
|
|
/* Note: no sample format conversion necessary for S1000/S3000 */
|
|
sbuf=wavbuf;
|
|
}
|
|
|
|
/* read sample to memory */
|
|
if (akai_read_file(0,sbuf,fp,hdrsize,hdrsize+samplesize)<0){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
|
|
if (fp->type==(u_char)AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
if (fp->osver==0){
|
|
/* S900 non-compressed sample format */
|
|
/* convert S900 non-compressed sample format into 16bit WAV sample format */
|
|
akai_sample900noncompr_sample2wav(sbuf,wavbuf,samplecountpart);
|
|
}else{
|
|
/* S900 compressed sample format */
|
|
/* convert S900 compressed sample format into 16bit WAV sample format */
|
|
i=akai_sample900compr_sample2wav(sbuf,wavbuf,samplesize,wavsamplesize);
|
|
if (i<wavsamplesize){
|
|
PRINTF_ERR("warning: incomplete sample data\n");
|
|
/* zero padding */
|
|
bzero(wavbuf+i,wavsamplesize-i);
|
|
}
|
|
}
|
|
}
|
|
/* Note: no sample format conversion necessary for S1000/S3000 */
|
|
}
|
|
|
|
if (what&SAMPLE2WAV_CREATE){
|
|
/* create WAV file */
|
|
if ((wavfd=OPEN(wavname,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0666))<0){
|
|
PERROR("create WAV");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
}
|
|
|
|
/* write WAV header */
|
|
if (wav_write_head(wavfd,
|
|
wavsamplesize,1,samplerate,16, /* 1: mono, 16: 16bit */
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
sizeof(struct wav_chunkhead_s)+hdrsize /* sample header chunk (see below) */
|
|
#else
|
|
0
|
|
#endif
|
|
)<0){
|
|
PRINTF_ERR("cannot write WAV header\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
|
|
if (wavsamplesize>0){
|
|
/* write WAV sample to WAV file */
|
|
if (WRITE(wavfd,wavbuf,wavsamplesize)!=(int)wavsamplesize){
|
|
PRINTF_ERR("cannot write WAV samples\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
}
|
|
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
{
|
|
struct wav_chunkhead_s wavchunkhead;
|
|
|
|
/* create sample header chunk */
|
|
if (fp->type==(u_char)AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
bcopy(WAV_CHUNKHEAD_AKAIS900SAMPLEHEADSTR,wavchunkhead.typestr,4);
|
|
}else if (fp->type==(u_char)AKAI_SAMPLE1000_FTYPE){
|
|
/* S1000 sample */
|
|
bcopy(WAV_CHUNKHEAD_AKAIS1000SAMPLEHEADSTR,wavchunkhead.typestr,4);
|
|
}else{
|
|
/* S3000 sample */
|
|
bcopy(WAV_CHUNKHEAD_AKAIS3000SAMPLEHEADSTR,wavchunkhead.typestr,4);
|
|
}
|
|
wavchunkhead.csize[0]=0xff&hdrsize;
|
|
wavchunkhead.csize[1]=0xff&(hdrsize>>8);
|
|
wavchunkhead.csize[2]=0xff&(hdrsize>>16);
|
|
wavchunkhead.csize[3]=0xff&(hdrsize>>24);
|
|
/* write WAV chunk header */
|
|
if (WRITE(wavfd,(u_char *)&wavchunkhead,sizeof(struct wav_chunkhead_s))!=(int)sizeof(struct wav_chunkhead_s)){
|
|
PRINTF_ERR("cannot write WAV chunk\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
/* write sample header */
|
|
/* Note: use S3000 header as buffer for S900 header */
|
|
/* Note: S1000 header is contained within S3000 header */
|
|
if (WRITE(wavfd,(u_char *)&s3000hdr,hdrsize)!=(int)hdrsize){
|
|
PRINTF_ERR("cannot write WAV chunk\n");
|
|
goto akai_sample2wav_exit;
|
|
}
|
|
}
|
|
#endif
|
|
#if 1
|
|
PRINTF_OUT("sample exported to WAV\n");
|
|
#endif
|
|
}
|
|
|
|
ret=0; /* success */
|
|
|
|
akai_sample2wav_exit:
|
|
if (wavbuf!=NULL){
|
|
free(wavbuf);
|
|
}
|
|
if (fp->type==(u_char)AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
if (sbuf!=NULL){
|
|
free(sbuf);
|
|
}
|
|
}
|
|
if (what&SAMPLE2WAV_CREATE){
|
|
if (wavfd>=0){
|
|
CLOSE(wavfd);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
akai_wav2sample(int wavfd,char *wavname,struct vol_s *volp,u_int findex,
|
|
u_int type,int s9cflag,u_int osver,u_char *tagp,
|
|
u_int *bcountp,int what)
|
|
{
|
|
/* Note: static for multiple calls with different what */
|
|
struct file_s tmpfile;
|
|
struct akai_sample900_s s900hdr;
|
|
struct akai_sample3000_s s3000hdr;
|
|
static u_int hdrsize;
|
|
static u_int samplerate;
|
|
static u_int samplecount;
|
|
static u_int samplecountpart;
|
|
static u_int samplesize;
|
|
static u_char *sbuf;
|
|
static u_int wavchnr;
|
|
static u_int wavbitnr;
|
|
static int wavmono16flag;
|
|
static u_int wavsamplesize;
|
|
static u_int wavsamplecount;
|
|
static u_int wavch;
|
|
static u_char *wavbuf16;
|
|
static u_int wavbuf16size;
|
|
static u_char *wavbuf;
|
|
static char *errstrp;
|
|
static u_int nlen,nlenmax;
|
|
static char *tname;
|
|
static char fname[AKAI_NAME_LEN+4+1]; /* name (ASCII), +4 for ".<type>", +1 for '\0' */
|
|
static char sname[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
|
static int r;
|
|
static u_int bcount;
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
static u_int extrasize;
|
|
static int wavakaiheadfound;
|
|
#endif
|
|
static u_int i;
|
|
static int ret;
|
|
|
|
if (bcountp!=NULL){
|
|
*bcountp=0; /* no bytes read yet */
|
|
}
|
|
|
|
if (volp==NULL){
|
|
return -1;
|
|
}
|
|
|
|
/* check WAV name */
|
|
if (wavname==NULL){
|
|
return -1;
|
|
}
|
|
nlen=(u_int)strlen(wavname);
|
|
if ((nlen<4)||(strncasecmp(wavname+nlen-4,".wav",4)!=0)){
|
|
/* not a WAV file */
|
|
return 1; /* no error */
|
|
}
|
|
nlen-=4; /* remove suffix */
|
|
|
|
/* sample file type */
|
|
if (type==AKAI_FTYPE_FREE){ /* invalid file type? */
|
|
/* derive sample file type from volume type/file osver */
|
|
if (volp->type==AKAI_VOL_TYPE_S900){
|
|
/* S900 sample */
|
|
type=AKAI_SAMPLE900_FTYPE;
|
|
/* Note: ignore given osver, osver will be overwritten below */
|
|
}else{
|
|
#if 1
|
|
if (osver==AKAI_OSVER_S900VOL){
|
|
/* S900 sample */
|
|
type=AKAI_SAMPLE900_FTYPE;
|
|
}else if (osver<=AKAI_OSVER_S1100MAX){
|
|
/* S1000 sample */
|
|
type=AKAI_SAMPLE1000_FTYPE;
|
|
}else{
|
|
/* S3000 sample */
|
|
type=AKAI_SAMPLE3000_FTYPE;
|
|
}
|
|
#else
|
|
if (volp->type==AKAI_VOL_TYPE_S1000){
|
|
/* S1000 sample */
|
|
type=AKAI_SAMPLE1000_FTYPE;
|
|
}else if ((volp->type==AKAI_VOL_TYPE_S3000)||(volp->type==AKAI_VOL_TYPE_CD3000)){
|
|
/* S3000 sample */
|
|
type=AKAI_SAMPLE3000_FTYPE;
|
|
}else{
|
|
return -1;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
if (type==AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
hdrsize=sizeof(struct akai_sample900_s);
|
|
if (s9cflag){
|
|
/* S900 compressed sample format */
|
|
tname=".S9C";
|
|
}else{
|
|
/* S900 non-compressed sample format */
|
|
tname=".S9";
|
|
}
|
|
}else if (type==AKAI_SAMPLE1000_FTYPE){
|
|
/* S1000 sample */
|
|
hdrsize=sizeof(struct akai_sample1000_s);
|
|
tname=".S1";
|
|
}else if (type==AKAI_SAMPLE3000_FTYPE){
|
|
/* S3000 sample */
|
|
hdrsize=sizeof(struct akai_sample3000_s);
|
|
tname=".S3";
|
|
}else{
|
|
return -1;
|
|
}
|
|
|
|
wavmono16flag=1; /* XXX unknown yet */
|
|
wavbuf16=NULL; /* not allocated yet */
|
|
wavbuf=NULL; /* not allocated yet */
|
|
sbuf=NULL; /* not allocated yet */
|
|
ret=-1; /* no success so far */
|
|
bcount=0; /* no bytes read yet */
|
|
|
|
if (what&WAV2SAMPLE_OPEN){
|
|
/* open external WAV file */
|
|
if ((wavfd=akai_openreadonly_extfile(wavname))<0){
|
|
PERROR("open WAV");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}
|
|
|
|
/* read and parse WAV header */
|
|
if (wav_read_head(wavfd,&bcount,
|
|
&wavsamplesize,&wavchnr,&samplerate,&wavbitnr,
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
&extrasize,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
&errstrp)<0){
|
|
if (errstrp!=NULL){
|
|
PRINTF_ERR("%s\n",errstrp);
|
|
}
|
|
/* error, don't know how many bytes read */
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
|
|
/* check parameters */
|
|
if ((wavchnr!=1)&&(wavchnr!=2)){
|
|
PRINTF_ERR("invalid number of channels, must be mono or stereo\n");
|
|
/* unknown or unsupported */
|
|
ret=1; /* no error */
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
if ((wavbitnr!=8)&&(wavbitnr!=16)&&(wavbitnr!=24)&&(wavbitnr!=32)){
|
|
PRINTF_ERR("invalid WAV format, must be 8bit or 16bit or 24bit or 32bit PCM\n");
|
|
/* unknown or unsupported */
|
|
ret=1; /* no error */
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
if ((wavchnr==1)&&(wavbitnr==16)){
|
|
/* WAV file is mono 16bit */
|
|
wavmono16flag=1;
|
|
}else{
|
|
wavmono16flag=0;
|
|
}
|
|
|
|
/* number of samples in WAV file (per channel) */
|
|
/* Note: can be an odd number */
|
|
wavsamplecount=wavsamplesize/(wavchnr*(wavbitnr/8));
|
|
#if 0
|
|
if (wavsamplecount==0){
|
|
PRINTF_ERR("no samples in WAV file\n");
|
|
ret=1; /* no error */
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
#endif /* else: Note: wavesamplecount==0 is allowed here */
|
|
|
|
if (wavsamplecount>0){
|
|
/* determine number of samples and sample size */
|
|
if (type==AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
/* S900 sample */
|
|
/* number of samples per part */
|
|
samplecountpart=(wavsamplecount+1)/2; /* round up */
|
|
samplecount=2*samplecountpart; /* samplecount must be an even number */
|
|
/* set samplesize for S900 non-compressed sample format */
|
|
/* Note: for S900 compressed sample format, samplesize will be overwritten below */
|
|
/* size in bytes */
|
|
samplesize=3*samplecountpart;
|
|
}else{
|
|
/* S1000/S3000 sample */
|
|
samplecountpart=0;
|
|
samplecount=wavsamplecount;
|
|
/* size in bytes */
|
|
samplesize=samplecount*2; /* *2 for 16bit per sample word */
|
|
}
|
|
|
|
/* allocate WAV 16bit sample buffer */
|
|
wavbuf16size=2*samplecount; /* *2 for 16bit per sample word in wavbuf16 */
|
|
if (wavmono16flag&&(wavbuf16size<wavsamplesize)){
|
|
/* Note: need at least wavsamplesize for wavbuf==wavbuf16 below */
|
|
wavbuf16size=wavsamplesize;
|
|
}
|
|
wavbuf16=(u_char *)malloc(wavbuf16size);
|
|
if (wavbuf16==NULL){
|
|
PRINTF_ERR("cannot allocate WAV 16bit buffer\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
if (type!=AKAI_SAMPLE900_FTYPE){ /* S1000/S3000 sample? */
|
|
/* use wavbuf16 as sample buffer */
|
|
sbuf=wavbuf16;
|
|
}
|
|
/* Note: for S900 sample, sbuf will be allocated below */
|
|
|
|
/* WAV sample buffer */
|
|
if (wavmono16flag){ /* WAV file is mono 16bit? */
|
|
/* use wavbuf16 as WAV sample buffer */
|
|
wavbuf=wavbuf16;
|
|
}else{
|
|
/* allocate WAV sample buffer */
|
|
wavbuf=(u_char *)malloc(wavsamplesize);
|
|
if (wavbuf==NULL){
|
|
PRINTF_ERR("cannot allocate WAV buffer\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}
|
|
|
|
/* read WAV sample to memory */
|
|
if (READ(wavfd,wavbuf,wavsamplesize)!=(int)wavsamplesize){
|
|
PRINTF_ERR("cannot read sample\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
bcount+=wavsamplesize;
|
|
|
|
/* zero padding if necessary */
|
|
/* Note: must be after READ to wavbuf for case that wavbuf==wavbuf16 */
|
|
if (samplecount>wavsamplecount){
|
|
/* 16bit sample word */
|
|
wavbuf16[wavsamplecount*2+1]=0x00;
|
|
wavbuf16[wavsamplecount*2+0]=0x00;
|
|
}
|
|
}else{
|
|
samplecountpart=0;
|
|
samplecount=0;
|
|
samplesize=0;
|
|
}
|
|
|
|
/* correct osver if necessary */
|
|
if (type==AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
/* Note: here, samplesize==non-compressed sample size in bytes */
|
|
if (s9cflag){
|
|
/* S900 compressed sample format */
|
|
/* set osver=number of un-compressed floppy blocks */
|
|
/* Note: without sample header */
|
|
osver=(samplesize+AKAI_FL_BLOCKSIZE-1)/AKAI_FL_BLOCKSIZE; /* round up */
|
|
if (osver==0){ /* unsuitable osver? */
|
|
osver=1; /* XXX non zero */
|
|
}
|
|
}else{
|
|
/* S900 non-compressed sample format */
|
|
osver=0;
|
|
}
|
|
}else if (type==AKAI_SAMPLE1000_FTYPE){
|
|
/* S1000 sample */
|
|
if ((osver==AKAI_OSVER_S900VOL)||(osver>AKAI_OSVER_S1100MAX)){
|
|
osver=AKAI_OSVER_S1000MAX; /* XXX */
|
|
}
|
|
}else{
|
|
/* S3000 sample */
|
|
if ((osver==AKAI_OSVER_S900VOL)||(osver>AKAI_OSVER_S3000MAX)){
|
|
osver=AKAI_OSVER_S3000MAX; /* XXX */
|
|
}
|
|
}
|
|
|
|
/* sample name */
|
|
if ((type==AKAI_SAMPLE900_FTYPE)||(volp->type==AKAI_VOL_TYPE_S900)){ /* S900 sample or S900 volume? */
|
|
nlenmax=AKAI_NAME_LEN_S900;
|
|
}else{
|
|
nlenmax=AKAI_NAME_LEN;
|
|
}
|
|
if (wavchnr==1){
|
|
/* mono */
|
|
if (nlen>nlenmax){
|
|
nlen=nlenmax;
|
|
}
|
|
bcopy(wavname,sname,nlen);
|
|
sname[nlen]='\0';
|
|
}else{
|
|
/* stereo */
|
|
if (nlen>nlenmax-2){
|
|
nlen=nlenmax-2;
|
|
}
|
|
bcopy(wavname,sname,nlen);
|
|
for (i=nlen;i<nlenmax-2;i++){
|
|
sname[i]=' ';
|
|
}
|
|
sname[i++]='-';
|
|
sname[i++]='L'; /* left channel first */
|
|
sname[i]='\0';
|
|
}
|
|
sprintf(fname,"%s%s",sname,tname);
|
|
/* Note: if stereo, channel letter in sname,fname will be updated below */
|
|
|
|
/* sample header */
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
/* check for sample header chunk in WAV file */
|
|
{
|
|
u_int wavakaiheadsearchtype;
|
|
int wavakaiheadtype;
|
|
u_int wavakaiheadsize;
|
|
u_int bc;
|
|
|
|
/* matching type */
|
|
if (type==AKAI_SAMPLE900_FTYPE){
|
|
wavakaiheadsearchtype=WAV_AKAIHEADTYPE_SAMPLE900;
|
|
}else if (type==AKAI_SAMPLE1000_FTYPE){
|
|
wavakaiheadsearchtype=WAV_AKAIHEADTYPE_SAMPLE1000;
|
|
}else{
|
|
wavakaiheadsearchtype=WAV_AKAIHEADTYPE_SAMPLE3000;
|
|
}
|
|
|
|
wavakaiheadtype=wav_find_akaihead(wavfd,&bc,&wavakaiheadsize,extrasize,wavakaiheadsearchtype);
|
|
if (wavakaiheadtype<0){
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
bcount+=bc;
|
|
|
|
if ((wavakaiheadtype==(int)wavakaiheadsearchtype)&&(wavakaiheadsize==hdrsize)){
|
|
/* found matching sample header chunk */
|
|
wavakaiheadfound=1;
|
|
}else{
|
|
wavakaiheadfound=0;
|
|
}
|
|
}
|
|
#endif
|
|
if (type==AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
if (wavakaiheadfound){
|
|
/* read S900 sample header */
|
|
if (READ(wavfd,(u_char *)&s900hdr,hdrsize)!=(int)hdrsize){
|
|
PRINTF_ERR("cannot read sample header\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
bcount+=hdrsize;
|
|
#if 1
|
|
PRINTF_OUT("S900 sample header imported from WAV\n");
|
|
#endif
|
|
}else
|
|
#endif
|
|
{
|
|
/* create S900 sample header */
|
|
bzero(&s900hdr,sizeof(struct akai_sample900_s));
|
|
|
|
s900hdr.srate[1]=0xff&(samplerate>>8);
|
|
s900hdr.srate[0]=0xff&samplerate;
|
|
|
|
s900hdr.npitch[1]=0xff&(SAMPLE900_NPITCH_DEF>>8); /* XXX */
|
|
s900hdr.npitch[0]=0xff&SAMPLE900_NPITCH_DEF; /* XXX */
|
|
|
|
s900hdr.pmode=SAMPLE900_PMODE_ONESHOT; /* XXX */
|
|
|
|
/* Note: use wavsamplecount for end */
|
|
s900hdr.end[3]=0xff&(wavsamplecount>>24);
|
|
s900hdr.end[2]=0xff&(wavsamplecount>>16);
|
|
s900hdr.end[1]=0xff&(wavsamplecount>>8);
|
|
s900hdr.end[0]=0xff&wavsamplecount;
|
|
|
|
/* Note: use wavsamplecount for llen */
|
|
s900hdr.llen[3]=0xff&(wavsamplecount>>24);
|
|
s900hdr.llen[2]=0xff&(wavsamplecount>>16);
|
|
s900hdr.llen[1]=0xff&(wavsamplecount>>8);
|
|
s900hdr.llen[0]=0xff&wavsamplecount;
|
|
|
|
s900hdr.dir=SAMPLE900_DIR_NORM; /* XXX */
|
|
}
|
|
|
|
/* set correct slen */
|
|
s900hdr.slen[3]=0xff&(samplecount>>24);
|
|
s900hdr.slen[2]=0xff&(samplecount>>16);
|
|
s900hdr.slen[1]=0xff&(samplecount>>8);
|
|
s900hdr.slen[0]=0xff&samplecount;
|
|
}else{
|
|
/* S1000/S3000 sample */
|
|
#ifndef WAV_AKAIHEAD_DISABLE
|
|
if (wavakaiheadfound){
|
|
/* read S1000/S3000 sample header */
|
|
/* Note: S1000 header is contained within S3000 header */
|
|
if (READ(wavfd,(u_char *)&s3000hdr,hdrsize)!=(int)hdrsize){
|
|
PRINTF_ERR("cannot read sample header\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
bcount+=hdrsize;
|
|
#if 1
|
|
if (type==AKAI_SAMPLE1000_FTYPE){
|
|
PRINTF_OUT("S1000 sample header imported from WAV\n");
|
|
}else{
|
|
PRINTF_OUT("S3000 sample header imported from WAV\n");
|
|
}
|
|
#endif
|
|
}else
|
|
#endif
|
|
{
|
|
/* create S3000 sample header */
|
|
/* Note: S1000 header is contained within S3000 header */
|
|
bzero(&s3000hdr,sizeof(struct akai_sample3000_s));
|
|
|
|
s3000hdr.s1000.blockid=SAMPLE1000_BLOCKID;
|
|
s3000hdr.s1000.bandw=SAMPLE1000_BANDW_20KHZ; /* XXX */
|
|
s3000hdr.s1000.rkey=60; /* XXX */
|
|
s3000hdr.s1000.dummy1=0x80; /* XXX */
|
|
|
|
/* Note: use wavsamplecount-1 for end */
|
|
s3000hdr.s1000.end[3]=0xff&((wavsamplecount-1)>>24);
|
|
s3000hdr.s1000.end[2]=0xff&((wavsamplecount-1)>>16);
|
|
s3000hdr.s1000.end[1]=0xff&((wavsamplecount-1)>>8);
|
|
s3000hdr.s1000.end[0]=0xff&(wavsamplecount-1);
|
|
|
|
s3000hdr.s1000.stpaira[1]=0xff&(AKAI_SAMPLE1000_STPAIRA_NONE>>8);
|
|
s3000hdr.s1000.stpaira[0]=0xff&AKAI_SAMPLE1000_STPAIRA_NONE;
|
|
|
|
s3000hdr.s1000.srate[1]=0xff&(samplerate>>8);
|
|
s3000hdr.s1000.srate[0]=0xff&samplerate;
|
|
}
|
|
|
|
/* set correct slen */
|
|
s3000hdr.s1000.slen[3]=0xff&(samplecount>>24);
|
|
s3000hdr.s1000.slen[2]=0xff&(samplecount>>16);
|
|
s3000hdr.s1000.slen[1]=0xff&(samplecount>>8);
|
|
s3000hdr.s1000.slen[0]=0xff&samplecount;
|
|
}
|
|
/* Note: RAM name of sample in sample header will be set below */
|
|
|
|
/* process WAV channels */
|
|
wavch=0;
|
|
for (;;){
|
|
if (wavsamplecount>0){
|
|
if (!wavmono16flag){ /* WAV file is not mono 16bit? */
|
|
/* de-interleave WAV channels and convert sample format */
|
|
if (wavbitnr==8){
|
|
/* convert 8bit WAV sample format into 16bit WAV sample format */
|
|
for (i=0;i<wavsamplecount;i++){
|
|
wavbuf16[i*2+1]=0x80^wavbuf[wavchnr*i+wavch]; /* toggle sign bit */
|
|
wavbuf16[i*2+0]=0x00;
|
|
}
|
|
}else if (wavbitnr==16){
|
|
/* keep 16bit WAV sample format */
|
|
for (i=0;i<wavsamplecount;i++){
|
|
wavbuf16[i*2+0]=wavbuf[(wavchnr*i+wavch)*2+0];
|
|
wavbuf16[i*2+1]=wavbuf[(wavchnr*i+wavch)*2+1];
|
|
}
|
|
}else if (wavbitnr==24){
|
|
/* convert 24bit WAV sample format into 16bit WAV sample format */
|
|
for (i=0;i<wavsamplecount;i++){
|
|
/* Note: copy upper 16 bits, discard lower 8 bits */
|
|
wavbuf16[i*2+0]=wavbuf[(wavchnr*i+wavch)*3+1];
|
|
wavbuf16[i*2+1]=wavbuf[(wavchnr*i+wavch)*3+2];
|
|
}
|
|
}else if (wavbitnr==32){
|
|
/* convert 32bit WAV sample format into 16bit WAV sample format */
|
|
for (i=0;i<wavsamplecount;i++){
|
|
/* Note: copy upper 16 bits, discard lower 16 bits */
|
|
wavbuf16[i*2+0]=wavbuf[(wavchnr*i+wavch)*4+2];
|
|
wavbuf16[i*2+1]=wavbuf[(wavchnr*i+wavch)*4+3];
|
|
}
|
|
}
|
|
} /* Note: else: wavbuf==wavbuf16 */
|
|
|
|
if ((type==AKAI_SAMPLE900_FTYPE)&&s9cflag){ /* S900 compressed sample format? */
|
|
/* determine sample size */
|
|
/* first pass to convert 16bit WAV sample format into S900 compressed sample format */
|
|
/* Note: first pass of akai_sample900compr_wav2sample() requires 16bit WAV sample to be loaded to wavbuf16 */
|
|
r=akai_sample900compr_wav2sample(NULL,wavbuf16,samplecountpart); /* NULL: first pass */
|
|
if (r<0){
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
/* size in bytes */
|
|
samplesize=(u_int)r;
|
|
}
|
|
/* check sample size */
|
|
if (hdrsize+samplesize>AKAI_FILE_SIZEMAX){
|
|
PRINTF_ERR("WAV file is too large\n");
|
|
/* unknown or unsupported */
|
|
ret=1; /* no error */
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
if (type==AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
/* allocate sample buffer */
|
|
sbuf=(u_char *)malloc(samplesize);
|
|
if (sbuf==NULL){
|
|
PRINTF_ERR("cannot allocate sample buffer\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (wavch==1){ /* right channel? */
|
|
/* update sample name */
|
|
i=nlenmax-1;
|
|
sname[i]='R'; /* right channel */
|
|
fname[i]=sname[i];
|
|
}
|
|
|
|
#ifdef WAV2SAMPLE_OVERWRITE
|
|
if ((findex==AKAI_CREATE_FILE_NOINDEX)
|
|
/* check if destination file already exists */
|
|
&&(akai_find_file(volp,&tmpfile,fname)==0)){
|
|
/* exists */
|
|
if (what&WAV2SAMPLE_OVERWRITE){
|
|
/* delete file */
|
|
if (akai_delete_file(&tmpfile)<0){
|
|
PRINTF_ERR("cannot overwrite existing file\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}else{
|
|
PRINTF_ERR("file name already used\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* create file */
|
|
/* Note: akai_create_file() will correct osver if necessary */
|
|
if (akai_create_file(volp,&tmpfile,
|
|
hdrsize+samplesize,
|
|
findex,
|
|
fname,
|
|
osver,
|
|
tagp)<0){
|
|
PRINTF_ERR("cannot create file\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
|
|
if (type==AKAI_SAMPLE900_FTYPE){
|
|
/* S900 sample */
|
|
|
|
/* set RAM name of sample in sample header */
|
|
/* Note: akai_fixramname() not needed afterwards */
|
|
ascii2akai_name(sname,(u_char *)s900hdr.name,1); /* 1: S900 */
|
|
|
|
/* write sample header */
|
|
if (akai_write_file(0,(u_char *)&s900hdr,&tmpfile,0,hdrsize)<0){
|
|
PRINTF_ERR("cannot write sample header\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
|
|
if (wavsamplecount>0){
|
|
if (s9cflag){
|
|
/* second pass to convert 16bit WAV sample format into S900 compressed sample format */
|
|
if (akai_sample900compr_wav2sample(sbuf,wavbuf16,samplecountpart)<0){ /* sbuf!=NULL: second pass */
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}else{
|
|
/* convert 16bit WAV sample format into S900 non-compressed sample format */
|
|
akai_sample900noncompr_wav2sample(sbuf,wavbuf16,samplecountpart);
|
|
}
|
|
}
|
|
}else{
|
|
/* S1000/S3000 sample */
|
|
|
|
/* set RAM name of sample in sample header */
|
|
/* Note: akai_fixramname() not needed afterwards */
|
|
ascii2akai_name(sname,s3000hdr.s1000.name,0); /* 0: not S900 */
|
|
|
|
/* write sample header */
|
|
if (akai_write_file(0,(u_char *)&s3000hdr,&tmpfile,0,hdrsize)<0){
|
|
PRINTF_ERR("cannot write sample header\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
|
|
/* Note: sbuf==wavbuf16 for S1000/S3000 sample */
|
|
}
|
|
|
|
if (wavsamplecount>0){
|
|
/* write sample */
|
|
if (akai_write_file(0,sbuf,&tmpfile,hdrsize,hdrsize+samplesize)<0){
|
|
PRINTF_ERR("cannot write sample\n");
|
|
goto akai_wav2sample_exit;
|
|
}
|
|
}
|
|
|
|
if (wavchnr==1){ /* mono? */
|
|
#if 1
|
|
PRINTF_OUT("sample imported from WAV\n");
|
|
#endif
|
|
break; /* done */
|
|
} /* else: stereo */
|
|
#if 1
|
|
PRINTF_OUT("%s sample imported from WAV\n",(wavch==0)?"left":"right");
|
|
#endif
|
|
|
|
/* next WAV channel */
|
|
wavch++;
|
|
if (wavch>=wavchnr){
|
|
break; /* done */
|
|
}
|
|
if (findex!=AKAI_CREATE_FILE_NOINDEX){
|
|
findex++; /* XXX next file index */
|
|
}
|
|
if (type==AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
if (sbuf!=NULL){
|
|
free(sbuf);
|
|
sbuf=NULL;
|
|
}
|
|
if (s9cflag){
|
|
akai_sample900compr_wav2sample(NULL,NULL,0); /* NULL,NULL: free buffers if still allocated */
|
|
}
|
|
}
|
|
}
|
|
|
|
ret=0; /* success */
|
|
|
|
akai_wav2sample_exit:
|
|
if (wavbuf16!=NULL){
|
|
free(wavbuf16);
|
|
}
|
|
if ((!wavmono16flag)&&(wavbuf!=NULL)){
|
|
free(wavbuf);
|
|
}
|
|
if (type==AKAI_SAMPLE900_FTYPE){ /* S900 sample? */
|
|
if (sbuf!=NULL){
|
|
free(sbuf);
|
|
}
|
|
if (s9cflag){
|
|
akai_sample900compr_wav2sample(NULL,NULL,0); /* NULL,NULL: free buffers if still allocated */
|
|
}
|
|
}
|
|
if (what&WAV2SAMPLE_OPEN){
|
|
if (wavfd>=0){
|
|
CLOSE(wavfd);
|
|
}
|
|
}
|
|
if (bcountp!=NULL){
|
|
*bcountp=bcount;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|