ares-openbsd/thirdparty/TZXFile/TZXAudioGenerator.cpp

166 行
4.3 KiB
C++

//#include "..\stdafx.h"
#include "TZXAudioGenerator.h"
#include <stdlib.h>
#include "TZXFile.h"
#include <stdio.h>
#include <memory.h>
#define SECONDS_PER_BLOCK_CHUNK 60
#define BLOCK_SIZE (TZX_AUDIO_DATARATE * SECONDS_PER_BLOCK_CHUNK)
#define AUDIO_BUFFER_LENGTH (BLOCK_SIZE * m_nAudioBlocks)
#define HI 115
#define LO -115
TZXAudioGenerator::TZXAudioGenerator()
{
m_pAudioData = (char *)malloc(BLOCK_SIZE);
m_nAudioDataLengthinSamples = 0;
m_nAudioBlocks = 1;
m_bAmp = false;
}
TZXAudioGenerator::~TZXAudioGenerator()
{
}
void TZXAudioGenerator::SetAmp(bool bAmp)
{
m_bAmp = bAmp;
}
void TZXAudioGenerator::AddByte(char byte)
{
if (m_nAudioDataLengthinSamples == AUDIO_BUFFER_LENGTH)
{
// Need to increas the size of the buffer
ExtendAudioBuffer();
}
m_pAudioData[m_nAudioDataLengthinSamples] = byte;
m_nAudioDataLengthinSamples++;
}
void TZXAudioGenerator::ExtendAudioBuffer()
{
//printf("Debug: extending audio buffer to %d bytes\n", AUDIO_BUFFER_LENGTH);
char *pNewBuffer = (char *)malloc((m_nAudioBlocks + 1)*BLOCK_SIZE);
char *pOldBuffer = m_pAudioData;
memcpy(pNewBuffer, pOldBuffer, m_nAudioDataLengthinSamples);
m_pAudioData = pNewBuffer;
m_nAudioBlocks++;
free(pOldBuffer);
}
void TZXAudioGenerator::GeneratePulse(int lengthInTStates, bool toggleAmp)
{
// Calculate the length of the pulse in terms of samples
// Note this method is not completely accurate so may need some finessing for very high speed turbo loaders to work accurately...
double cycle = (double)TZX_AUDIO_DATARATE / (double)TZX_TSTATES_PER_SECOND;
int samples = ((unsigned int)(0.5 + (cycle*(double)lengthInTStates)));
for (int i = 0; i < samples; i++)
{
if (m_bAmp) AddByte(HI); else AddByte(LO);
}
// Automatically toggle the state unless we are specifically told not to
if (toggleAmp)
{
m_bAmp = !m_bAmp;
}
}
void TZXAudioGenerator::ResetBuffer()
{
free(m_pAudioData);
m_pAudioData = (char *)malloc(BLOCK_SIZE);
m_nAudioDataLengthinSamples = 0;
m_nAudioBlocks = 1;
m_bAmp = false;
}
int TZXAudioGenerator::GetCurrentLength()
{
return m_nAudioDataLengthinSamples;
}
void TZXAudioGenerator::AddSilence(int nLengthInMS)
{
int samplesToAdd = (nLengthInMS * TZX_AUDIO_DATARATE) / 1000;
if (nLengthInMS > 1 && m_bAmp)
{
int nRemainder = nLengthInMS - 1;
AddSilence(1);
m_bAmp = false;
AddSilence(nRemainder);
}
else {
for (int i = 0; i < samplesToAdd; i++)
{
if (m_bAmp) AddByte(HI); else AddByte(LO);
}
}
}
char *TZXAudioGenerator::GetAudioBufferPtr()
{
return m_pAudioData;
}
bool TZXAudioGenerator::SaveAsUncompressedWav(const char *szFilename)
{
FILE *hFile = NULL;
hFile = fopen(szFilename, "wb");
if (hFile == NULL) return false;
// We create an uncompressed wav and manually hack the header together according to the data at the website below
// http://www.topherlee.com/software/pcm-tut-wavformat.html
char *riff = (char *)"RIFF";
if (fwrite(riff, 4, 1, hFile) != 1) { fclose(hFile); return false; }
int fileLength = m_nAudioDataLengthinSamples + 44;
if (fwrite(&fileLength, 4, 1, hFile) != 1) { fclose(hFile); return false; }
char *wave = (char *)"WAVEfmt ";
if (fwrite(wave, 8, 1, hFile) != 1) { fclose(hFile); return false; }
int formatDataLength = 16;
if (fwrite(&formatDataLength, 4, 1, hFile) != 1) { fclose(hFile); return false; }
short formatType = 1; // PCM
if (fwrite(&formatType, 2, 1, hFile) != 1) { fclose(hFile); return false; }
short channels = 1;
if (fwrite(&channels, 2, 1, hFile) != 1) { fclose(hFile); return false; }
int sampleRate = TZX_AUDIO_DATARATE;
if (fwrite(&sampleRate, 4, 1, hFile) != 1) { fclose(hFile); return false; }
if (fwrite(&sampleRate, 4, 1, hFile) != 1) { fclose(hFile); return false; }
short bytesPerSample = 1;
if (fwrite(&bytesPerSample, 2, 1, hFile) != 1) { fclose(hFile); return false; }
int bitsPerSample = 8;
if (fwrite(&bitsPerSample, 2, 1, hFile) != 1) { fclose(hFile); return false; }
char *data = (char *)"data";
if (fwrite(data, 4, 1, hFile) != 1) { fclose(hFile); return false; }
int dataSize = m_nAudioDataLengthinSamples;
if (fwrite(&dataSize, 4, 1, hFile) != 1) { fclose(hFile); return false; }
for (int i = 0; i < dataSize; i++)
{
int n = m_pAudioData[i];
n = n + 128;
unsigned char b = (unsigned char) n;
if (fwrite(&b, 1, 1, hFile) != 1) { fclose(hFile); return false; }
}
fclose(hFile);
return true;
}