furnace/src/engine/fileOps/pps.cpp
2025-06-15 17:31:32 +04:00

117 lines
3 KiB
C++

/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2025 tildearrow and contributors
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "fileOpsCommon.h"
class DivEngine;
//PPS AY-3-8910 sample bank
/* =======================================
Header
=======================================
0x0000 - 0x0053 14 * {
Pointer to Sample Data Start (1h)
Length of Sample Data (1h)
"Pitch"(?) (1b)
Volume Reduction (1b)
}
(0x0000 0x0000 [0x00 0x00] -> no sample for this instrument ID)
}
=======================================
Body
=======================================
Stream of Sample Data {
4-Bit Unsigned
(afaict)
Mono
16Hz
(based on tests, maybe alternatively 8kHz)
} */
#define PPS_BANK_SIZE 14
#define PPS_SAMPLE_RATE 16000
typedef struct
{
uint16_t start_pointer;
uint16_t sample_length;
uint8_t _pitch;
uint8_t _vol;
} PPS_HEADER;
void DivEngine::loadPPS(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath)
{
try
{
reader.seek(0, SEEK_SET);
PPS_HEADER headers[PPS_BANK_SIZE];
for(int i = 0; i < PPS_BANK_SIZE; i++)
{
headers[i].start_pointer = (unsigned short)reader.readS();
headers[i].sample_length = (unsigned short)reader.readS();
headers[i]._pitch = (unsigned char)reader.readC();
headers[i]._vol = (unsigned char)reader.readC();
}
for(int i = 0; i < PPS_BANK_SIZE; i++)
{
if(headers[i].start_pointer != 0 || headers[i].sample_length != 0
|| headers[i]._pitch != 0 || headers[i]._vol != 0)
{
DivSample* s = new DivSample;
s->rate = PPS_SAMPLE_RATE;
s->centerRate = PPS_SAMPLE_RATE;
s->depth = DIV_SAMPLE_DEPTH_4BIT;
s->init(headers[i].sample_length*2); //byte per sample
reader.seek((int)headers[i].start_pointer, SEEK_SET);
for(int j = 0; j < headers[i].sample_length; j++)
{
s->data4[j] = reader.readC();
}
ret.push_back(s);
logI("pps: start %d len %d", headers[i].start_pointer, headers[i].sample_length);
}
}
}
catch (EndOfFileException& e)
{
lastError=_("premature end of file");
logE("premature end of file");
}
}