hxtools/smm/pcspkr_pcm.c

66 lines
1.7 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2002-2007 Jan Engelhardt
/*
* pcspkr_pcm.c - output as PCM
*/
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "pcspkr.h"
/**
* dynamic_qi
* @pcsp: pc speaker struct
* @x: time
*
* A pure sine wave does not sound at all like a PC speaker. A square wave on
* the other hand is very hard (hardness, not difficulty). Mix square and sine
* according to parameters.
*/
static inline double dynamic_qi(const struct pcspkr *pcsp, double x)
{
double i = sin(x);
double q = (i > 0) ? 1 : -1;
return (pcsp->prop_square * q + pcsp->prop_sine * i) /
(pcsp->prop_square + pcsp->prop_sine);
}
/**
* pcspkr_output - produce waves
* @state: pcspkr state
* @frequency: tone frequency
* @duration: duration, in samples
* (number of samples in a second given by @state->sampling_rate)
* @af_pause: after-pause, in samples
*
* Outputs 16-bit PCM samples of a @freq Hz tone for @duration to @sp->fp,
* with an optional pause.
*/
void pcspkr_output(const struct pcspkr *pcsp, long frequency,
long duration, long af_pause)
{
int16_t value;
long sample;
for (sample = 0; sample < duration; ++sample) {
value = 32767 * dynamic_qi(pcsp,
2.0 * M_PI * frequency * sample / pcsp->sample_rate) *
pcsp->volume;
fwrite(&value, sizeof(value), 1, pcsp->file_ptr);
}
value = 0;
for (sample = 0; sample < af_pause; ++sample)
fwrite(&value, sizeof(value), 1, pcsp->file_ptr);
}
void pcspkr_silence(const struct pcspkr *pcsp, long duration)
{
static const uint16_t value_16 = 0;
long sample;
for (sample = 0; sample < duration; ++sample)
fwrite(&value_16, sizeof(value_16), 1, pcsp->file_ptr);
}