Descent3/stream_audio/osfarchive.cpp
2024-05-24 20:57:17 -04:00

239 lines
5.5 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Main/streamaudio/osfarchive.cpp $
* $Revision: 7 $
* $Date: 4/14/99 1:47a $
* $Author: Jeff $
*
* OSF File Reader
*
* $Log: /DescentIII/Main/streamaudio/osfarchive.cpp $
*
* 7 4/14/99 1:47a Jeff
* fixed case mismatched #includes
*
* 6 4/02/99 4:32p Samir
* fixed problem with really long stream names screwing up the osf header.
*
* 5 4/01/99 4:50p Matt
* Took out Warning() function, chaning those calls to mprintf()
*
* 4 3/09/99 6:36p Samir
* try catch blocks.
*
* 3 10/21/98 8:13p Samir
* fixed music utils problems.
*
* 2 7/24/98 5:18p Samir
* moved OSF header to end of file.
*
* 1 7/20/98 2:54p Samir
* initial revision.
*
* $NoKeywords: $
*/
#include "streamaudio.h"
#include "cfile.h"
#include "pserror.h"
#include <string.h>
OSFArchive::OSFArchive() {
m_fp = NULL;
m_length = 0;
m_type = 0;
m_comp = 0;
m_flags = 0;
m_rate = 0;
m_writemode = false;
m_name[0] = 0;
}
OSFArchive::~OSFArchive() {
if (m_fp) {
cfclose(m_fp);
m_fp = NULL;
}
}
bool OSFArchive::Open(const char *filename, bool write) {
char tag[8];
ASSERT(!m_fp);
try {
if (write)
m_fp = cfopen(filename, "wb");
else
m_fp = cfopen(filename, "rb");
if (!m_fp)
return false;
m_writemode = write;
if (m_writemode)
return true;
// okay, if we are in read mode, then we read in the header NOW
memset(tag, 0, sizeof(tag));
cfseek(m_fp, -OSF_HDR_SIZE, SEEK_END);
cf_ReadBytes((uint8_t *)tag, strlen(OSF_TAG), m_fp);
if (strcmp(OSF_TAG, tag) != 0) {
mprintf(0, "Illegal OSF file format for %s.\n", filename);
cfclose(m_fp);
m_fp = NULL;
return false;
}
// read in rest of header.
m_type = (uint8_t)cf_ReadByte(m_fp);
m_comp = (uint8_t)cf_ReadByte(m_fp);
m_flags = (uint8_t)cf_ReadByte(m_fp);
m_rate = (uint32_t)cf_ReadByte(m_fp);
if (m_type == OSF_DIGITAL_STRM) {
if (m_rate == 11)
m_rate = 11025;
else if (m_rate == 22)
m_rate = 22050;
else if (m_rate == 44)
m_rate = 44100;
// read in aux header based off of type.
m_hdr.digi.measure = (uint32_t)cf_ReadInt(m_fp);
} else {
mprintf(0, "Unsupported OSF file type in %s!\n", filename);
cfclose(m_fp);
m_fp = NULL;
return false;
}
// read length.
m_length = (uint32_t)cf_ReadInt(m_fp);
cfseek(m_fp, -OSF_HDR_TITLE_OFS, SEEK_END);
if (!cf_ReadBytes((uint8_t *)m_name, OSF_HDR_TITLE_LEN, m_fp)) {
mprintf(0, "Stream title not found for %s.\n", filename);
cfclose(m_fp);
m_fp = NULL;
return false;
}
} catch (...) {
if (m_fp) {
try {
cfclose(m_fp);
} catch (...) {
}
m_fp = NULL;
}
return false;
}
m_datastart = 0;
OSFArchive::Rewind();
return true;
}
void OSFArchive::Close() {
if (m_fp) {
try {
cfclose(m_fp);
} catch (...) {
}
m_fp = NULL;
}
m_writemode = false;
}
void OSFArchive::Rewind() {
try {
cfseek(m_fp, m_datastart, SEEK_SET);
} catch (...) {
}
}
// write out operations.
bool OSFArchive::SaveHeader(uint8_t type, uint8_t comp, uint8_t flags, uint32_t rate, uint32_t length, void *hdr, const char *name) {
char chbuf[OSF_HDR_SIZE];
int hdrstart, hdrcur;
if (!m_fp || !m_writemode)
return false;
// write out data.
try {
char osftitle[OSF_HDR_TITLE_LEN];
memset((uint8_t *)chbuf, 0, OSF_HDR_SIZE);
cf_WriteBytes((uint8_t *)chbuf, OSF_HDR_SIZE, m_fp);
cfseek(m_fp, -OSF_HDR_SIZE, SEEK_CUR);
hdrstart = cftell(m_fp);
if (!cf_WriteBytes((uint8_t *)OSF_TAG, strlen(OSF_TAG), m_fp))
return false;
cf_WriteByte(m_fp, (int8_t)type);
cf_WriteByte(m_fp, (int8_t)comp);
cf_WriteByte(m_fp, (int8_t)flags);
if (type == OSF_DIGITAL_STRM) {
tOSFDigiHdr *digihdr = (tOSFDigiHdr *)hdr;
cf_WriteByte(m_fp, (rate == 11025) ? 11 : (rate == 22050) ? 22 : (rate == 44100) ? 44 : 0);
cf_WriteInt(m_fp, (int)digihdr->measure);
} else {
return false;
}
cf_WriteInt(m_fp, (int)length);
hdrcur = cftell(m_fp);
if ((hdrcur - hdrstart) > OSF_HDR_TITLE_OFS) {
mprintf(0, "stream header too big for title!\n");
return false;
}
cfseek(m_fp, OSF_HDR_TITLE_OFS - (hdrcur - hdrstart), SEEK_CUR);
strncpy(osftitle, name, OSF_HDR_TITLE_LEN);
osftitle[OSF_HDR_TITLE_LEN - 1] = 0;
if (!cf_WriteBytes((uint8_t *)name, OSF_HDR_TITLE_LEN, m_fp))
return false;
} catch (...) {
return false;
}
return true;
}
bool OSFArchive::WriteBlock(uint8_t *blk, int size) { return (cf_WriteBytes(blk, size, m_fp) < size) ? false : true; }
// read in operations.
int OSFArchive::Read(uint8_t *blk, int size) {
int retval;
try {
retval = cf_ReadBytes(blk, size, m_fp);
} catch (...) {
retval = 0;
}
return retval;
}