sound: update, simplify, and fix

This commit is contained in:
Christopher Mosher
2019-01-26 00:16:12 -05:00
parent 090080a117
commit 093c4dae2f
2 changed files with 59 additions and 123 deletions

View File

@@ -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, &amp, 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;
} }

View File

@@ -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();