mirror of
https://github.com/cmosher01/Epple-II.git
synced 2025-08-10 23:24:58 +00:00
sound: update, simplify, and fix
This commit is contained in:
@@ -16,149 +16,80 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "speakerclicker.h"
|
#include "speakerclicker.h"
|
||||||
#include <SDL2/SDL.h>
|
#include "e2const.h"
|
||||||
|
#include <SDL2/SDL_audio.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
std::deque<char> locbuf;
|
#define TICKS_PER_SAMPLE 50
|
||||||
volatile bool done;
|
|
||||||
SDL_cond* bufchg;
|
|
||||||
SDL_mutex* buflck;
|
|
||||||
volatile int silence;
|
|
||||||
|
|
||||||
// TODO figure out why sound is so choppy, and fix it
|
|
||||||
void fillbuf(void *userdata, Uint8 *stream, int len)
|
|
||||||
{
|
|
||||||
int tot(0);
|
|
||||||
while (len && !done)
|
|
||||||
{
|
|
||||||
// wait for locbuf to have some data
|
|
||||||
// (it gets filled up by tick() method)
|
|
||||||
SDL_LockMutex(buflck);
|
|
||||||
while (locbuf.empty() && !done)
|
|
||||||
{
|
|
||||||
SDL_CondWait(bufchg,buflck);
|
|
||||||
}
|
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
SDL_UnlockMutex(buflck);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (locbuf.size() > 0 && len > 0)
|
|
||||||
{
|
|
||||||
int v = locbuf.front();
|
|
||||||
*stream++ = v;
|
|
||||||
|
|
||||||
if (v < 0) v = -v;
|
|
||||||
tot += v;
|
|
||||||
|
|
||||||
--len;
|
|
||||||
locbuf.pop_front();
|
|
||||||
}
|
|
||||||
if (tot <= 0)
|
|
||||||
{
|
|
||||||
if (locbuf.size() >= 1024)
|
|
||||||
locbuf.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (locbuf.size() >= 65536)
|
|
||||||
locbuf.clear();
|
|
||||||
}
|
|
||||||
SDL_UnlockMutex(buflck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TICKS_PER_SAMPLE 21
|
|
||||||
|
|
||||||
SpeakerClicker::SpeakerClicker():
|
SpeakerClicker::SpeakerClicker():
|
||||||
clicked(false),
|
devid(0),
|
||||||
t(TICKS_PER_SAMPLE)
|
silence(128),
|
||||||
{
|
clicked(false),
|
||||||
done = false;
|
t(TICKS_PER_SAMPLE),
|
||||||
|
positive(false) {
|
||||||
SDL_AudioSpec audio;
|
SDL_AudioSpec audio;
|
||||||
audio.freq = 48000; // samples per second
|
audio.freq = E2Const::AVG_CPU_HZ/TICKS_PER_SAMPLE; // samples per second
|
||||||
audio.format = AUDIO_U8; // 8 bits (1 byte) per sample
|
audio.format = AUDIO_U8; // 8 bits (1 byte) per sample
|
||||||
audio.channels = 1; // mono
|
audio.channels = 1; // mono
|
||||||
audio.silence = 0;
|
audio.silence = 128;
|
||||||
audio.samples = 1024;
|
audio.samples = 512;
|
||||||
audio.callback = fillbuf;
|
audio.callback = 0;
|
||||||
audio.userdata = 0;
|
audio.userdata = 0;
|
||||||
SDL_AudioSpec obtained;
|
|
||||||
|
SDL_AudioSpec obtained;
|
||||||
obtained.callback = 0;
|
obtained.callback = 0;
|
||||||
obtained.userdata = 0;
|
obtained.userdata = 0;
|
||||||
|
|
||||||
if (SDL_OpenAudio(&audio,&obtained) != 0)
|
this->devid = SDL_OpenAudioDevice(0,0,&audio,&obtained,0);
|
||||||
{
|
if (!this->devid) {
|
||||||
done = true;
|
|
||||||
std::cerr << "Unable to initialize audio: " << SDL_GetError() << std::endl;
|
std::cerr << "Unable to initialize audio: " << SDL_GetError() << std::endl;
|
||||||
}
|
} else {
|
||||||
else
|
this->silence = obtained.silence;
|
||||||
{
|
|
||||||
bufchg = SDL_CreateCond();
|
|
||||||
buflck = SDL_CreateMutex();
|
|
||||||
silence = obtained.silence;
|
|
||||||
|
|
||||||
// std::cout << "initialized audio: " << std::endl;
|
std::cout << "initialized audio: " << std::endl;
|
||||||
// std::cout << "freq: " << obtained.freq << std::endl;
|
std::cout << " device ID: " << this->devid << std::endl;
|
||||||
// std::cout << "format: " << obtained.format << std::endl;
|
std::cout << " freq: " << obtained.freq << std::endl;
|
||||||
// std::cout << "channels: " << (int)obtained.channels << std::endl;
|
std::cout << " format: " << obtained.format << std::endl;
|
||||||
// std::cout << "silence: " << (int)obtained.silence << std::endl;
|
std::cout << " channels: " << (int)obtained.channels << std::endl;
|
||||||
// std::cout << "samples: " << obtained.samples << std::endl;
|
std::cout << " silence: " << (int)obtained.silence << std::endl;
|
||||||
// std::cout << "size: " << obtained.size << std::endl;
|
std::cout << " samples: " << obtained.samples << std::endl;
|
||||||
|
std::cout << " size: " << obtained.size << std::endl;
|
||||||
SDL_PauseAudio(0);
|
SDL_PauseAudioDevice(this->devid, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SpeakerClicker::~SpeakerClicker()
|
SpeakerClicker::~SpeakerClicker() {
|
||||||
{
|
if (!this->devid) {
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
done = true;
|
SDL_CloseAudioDevice(this->devid);
|
||||||
SDL_LockMutex(buflck);
|
|
||||||
SDL_CondSignal(bufchg);
|
|
||||||
SDL_UnlockMutex(buflck);
|
|
||||||
SDL_CloseAudio();
|
|
||||||
SDL_DestroyCond(bufchg);
|
|
||||||
SDL_DestroyMutex(buflck);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeakerClicker::tick()
|
void SpeakerClicker::tick() {
|
||||||
{
|
if (!this->devid) {
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
--this->t;
|
if (!--this->t) {
|
||||||
if (this->t <= 0)
|
std::uint8_t amp;
|
||||||
{
|
if (this->clicked) {
|
||||||
this->t = TICKS_PER_SAMPLE;
|
amp = this->positive ? this->silence+100u : this->silence-100u;
|
||||||
int amp;
|
|
||||||
if (this->clicked)
|
|
||||||
{
|
|
||||||
amp = this->positive ? silence+100 : silence-100;
|
|
||||||
this->positive = !this->positive;
|
this->positive = !this->positive;
|
||||||
this->clicked = false;
|
this->clicked = false;
|
||||||
}
|
} else {
|
||||||
else
|
amp = silence;
|
||||||
{
|
}
|
||||||
amp = silence;
|
const int failed = SDL_QueueAudio(this->devid, &, sizeof(amp));
|
||||||
}
|
if (failed) {
|
||||||
SDL_LockMutex(buflck);
|
std::cerr << "SDL_QueueAudio failed " << SDL_GetError() << std::endl;
|
||||||
locbuf.push_back(amp);
|
}
|
||||||
SDL_CondSignal(bufchg);
|
this->t = TICKS_PER_SAMPLE;
|
||||||
SDL_UnlockMutex(buflck);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeakerClicker::click()
|
void SpeakerClicker::click() {
|
||||||
{
|
|
||||||
this->clicked = true;
|
this->clicked = true;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
epple2
|
epple2
|
||||||
Copyright (C) 2008 by Christopher A. Mosher <cmosher01@gmail.com>
|
|
||||||
|
Copyright © 2008, 2019 by Christopher A. Mosher <cmosher01@gmail.com>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -18,13 +19,17 @@
|
|||||||
#ifndef SPEAKERCLICKER_H
|
#ifndef SPEAKERCLICKER_H
|
||||||
#define SPEAKERCLICKER_H
|
#define SPEAKERCLICKER_H
|
||||||
|
|
||||||
class SpeakerClicker
|
#include <cstdint>
|
||||||
{
|
#include <SDL2/SDL_audio.h>
|
||||||
private:
|
|
||||||
bool clicked;
|
class SpeakerClicker {
|
||||||
int t;
|
private:
|
||||||
|
SDL_AudioDeviceID devid;
|
||||||
|
std::uint8_t silence;
|
||||||
|
bool clicked;
|
||||||
|
std::uint8_t t;
|
||||||
bool positive;
|
bool positive;
|
||||||
public:
|
public:
|
||||||
SpeakerClicker();
|
SpeakerClicker();
|
||||||
~SpeakerClicker();
|
~SpeakerClicker();
|
||||||
void tick();
|
void tick();
|
||||||
|
Reference in New Issue
Block a user