mirror of https://github.com/adamdruppe/arsd.git
configurable params
This commit is contained in:
parent
a450ca7e4c
commit
1534a7fa19
|
@ -198,9 +198,9 @@ struct AudioOutputThread {
|
||||||
just live as a dummy mock object that you should not actually
|
just live as a dummy mock object that you should not actually
|
||||||
try to use.
|
try to use.
|
||||||
+/
|
+/
|
||||||
this(bool enable) {
|
this(bool enable, int SampleRate = 44100, int channels = 2) {
|
||||||
if(enable) {
|
if(enable) {
|
||||||
impl = new AudioPcmOutThreadImplementation();
|
impl = new AudioPcmOutThreadImplementation(SampleRate, channels);
|
||||||
impl.refcount++;
|
impl.refcount++;
|
||||||
impl.start();
|
impl.start();
|
||||||
impl.waitForInitialization();
|
impl.waitForInitialization();
|
||||||
|
@ -297,12 +297,17 @@ import core.thread;
|
||||||
---
|
---
|
||||||
+/
|
+/
|
||||||
final class AudioPcmOutThreadImplementation : Thread {
|
final class AudioPcmOutThreadImplementation : Thread {
|
||||||
private this() {
|
private this(int SampleRate, int channels) {
|
||||||
this.isDaemon = true;
|
this.isDaemon = true;
|
||||||
|
|
||||||
|
this.SampleRate = SampleRate;
|
||||||
|
this.channels = channels;
|
||||||
|
|
||||||
super(&run);
|
super(&run);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int SampleRate;
|
||||||
|
private int channels;
|
||||||
private int refcount;
|
private int refcount;
|
||||||
|
|
||||||
private void waitForInitialization() {
|
private void waitForInitialization() {
|
||||||
|
@ -630,8 +635,6 @@ import core.stdc.config;
|
||||||
version(linux) version=ALSA;
|
version(linux) version=ALSA;
|
||||||
version(Windows) version=WinMM;
|
version(Windows) version=WinMM;
|
||||||
|
|
||||||
enum SampleRate = 44100;
|
|
||||||
|
|
||||||
version(ALSA) {
|
version(ALSA) {
|
||||||
enum cardName = "default";
|
enum cardName = "default";
|
||||||
|
|
||||||
|
@ -690,12 +693,20 @@ struct AudioInput {
|
||||||
@disable this();
|
@disable this();
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
|
|
||||||
|
int channels;
|
||||||
|
int SampleRate;
|
||||||
|
|
||||||
/// Always pass card == 0.
|
/// Always pass card == 0.
|
||||||
this(int card) {
|
this(int card, int SampleRate = 44100, int channels = 2) {
|
||||||
assert(card == 0);
|
assert(card == 0);
|
||||||
|
|
||||||
|
assert(channels == 1 || channels == 2);
|
||||||
|
|
||||||
|
this.channels = channels;
|
||||||
|
this.SampleRate = SampleRate;
|
||||||
|
|
||||||
version(ALSA) {
|
version(ALSA) {
|
||||||
handle = openAlsaPcm(snd_pcm_stream_t.SND_PCM_STREAM_CAPTURE);
|
handle = openAlsaPcm(snd_pcm_stream_t.SND_PCM_STREAM_CAPTURE, SampleRate, channels);
|
||||||
} else version(WinMM) {
|
} else version(WinMM) {
|
||||||
event = CreateEvent(null, false /* manual reset */, false /* initially triggered */, null);
|
event = CreateEvent(null, false /* manual reset */, false /* initially triggered */, null);
|
||||||
|
|
||||||
|
@ -703,7 +714,7 @@ struct AudioInput {
|
||||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
format.nChannels = 2;
|
format.nChannels = 2;
|
||||||
format.nSamplesPerSec = SampleRate;
|
format.nSamplesPerSec = SampleRate;
|
||||||
format.nAvgBytesPerSec = SampleRate * 2 * 2; // two channels, two bytes per sample
|
format.nAvgBytesPerSec = SampleRate * channels * 2; // two channels, two bytes per sample
|
||||||
format.nBlockAlign = 4;
|
format.nBlockAlign = 4;
|
||||||
format.wBitsPerSample = 16;
|
format.wBitsPerSample = 16;
|
||||||
format.cbSize = 0;
|
format.cbSize = 0;
|
||||||
|
@ -724,11 +735,11 @@ struct AudioInput {
|
||||||
short[] read(short[] buffer) {
|
short[] read(short[] buffer) {
|
||||||
snd_pcm_sframes_t read;
|
snd_pcm_sframes_t read;
|
||||||
|
|
||||||
read = snd_pcm_readi(handle, buffer.ptr, buffer.length / 2 /* div number of channels apparently */);
|
read = snd_pcm_readi(handle, buffer.ptr, buffer.length / channels /* div number of channels apparently */);
|
||||||
if(read < 0)
|
if(read < 0)
|
||||||
throw new AlsaException("pcm read", cast(int)read);
|
throw new AlsaException("pcm read", cast(int)read);
|
||||||
|
|
||||||
return buffer[0 .. read * 2];
|
return buffer[0 .. read * channels];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// passes a buffer of data to fill
|
/// passes a buffer of data to fill
|
||||||
|
@ -840,6 +851,9 @@ struct AudioInput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
enum SampleRateFull = 44100;
|
||||||
|
|
||||||
/// Gives PCM output access (such as the speakers).
|
/// Gives PCM output access (such as the speakers).
|
||||||
struct AudioOutput {
|
struct AudioOutput {
|
||||||
version(ALSA) {
|
version(ALSA) {
|
||||||
|
@ -853,18 +867,26 @@ struct AudioOutput {
|
||||||
// be passed to a device driver and stored!
|
// be passed to a device driver and stored!
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
|
|
||||||
|
private int SampleRate;
|
||||||
|
private int channels;
|
||||||
|
|
||||||
/// Always pass card == 0.
|
/// Always pass card == 0.
|
||||||
this(int card) {
|
this(int card, int SampleRate = 44100, int channels = 2) {
|
||||||
assert(card == 0);
|
assert(card == 0);
|
||||||
|
|
||||||
|
assert(channels == 1 || channels == 2);
|
||||||
|
|
||||||
|
this.SampleRate = SampleRate;
|
||||||
|
this.channels = channels;
|
||||||
|
|
||||||
version(ALSA) {
|
version(ALSA) {
|
||||||
handle = openAlsaPcm(snd_pcm_stream_t.SND_PCM_STREAM_PLAYBACK);
|
handle = openAlsaPcm(snd_pcm_stream_t.SND_PCM_STREAM_PLAYBACK, SampleRate, channels);
|
||||||
} else version(WinMM) {
|
} else version(WinMM) {
|
||||||
WAVEFORMATEX format;
|
WAVEFORMATEX format;
|
||||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
format.nChannels = 2;
|
format.nChannels = cast(ushort) channels;
|
||||||
format.nSamplesPerSec = SampleRate;
|
format.nSamplesPerSec = SampleRate;
|
||||||
format.nAvgBytesPerSec = SampleRate * 2 * 2; // two channels, two bytes per sample
|
format.nAvgBytesPerSec = SampleRate * channels * 2; // two channels, two bytes per sample
|
||||||
format.nBlockAlign = 4;
|
format.nBlockAlign = 4;
|
||||||
format.wBitsPerSample = 16;
|
format.wBitsPerSample = 16;
|
||||||
format.cbSize = 0;
|
format.cbSize = 0;
|
||||||
|
@ -875,8 +897,8 @@ struct AudioOutput {
|
||||||
|
|
||||||
/// passes a buffer of data to fill
|
/// passes a buffer of data to fill
|
||||||
///
|
///
|
||||||
/// Data is assumed to be interleaved stereo, LE 16 bit, 44.1 kHz
|
/// Data is assumed to be interleaved stereo, LE 16 bit, 44.1 kHz (unless you change that in the ctor)
|
||||||
/// Each item in the array thus alternates between left and right channel
|
/// Each item in the array thus alternates between left and right channel (unless you change that in the ctor)
|
||||||
/// and it takes a total of 88,200 items to make one second of sound.
|
/// and it takes a total of 88,200 items to make one second of sound.
|
||||||
void delegate(short[]) fillData;
|
void delegate(short[]) fillData;
|
||||||
|
|
||||||
|
@ -902,18 +924,18 @@ struct AudioOutput {
|
||||||
if(ready > BUFFER_SIZE_FRAMES)
|
if(ready > BUFFER_SIZE_FRAMES)
|
||||||
ready = BUFFER_SIZE_FRAMES;
|
ready = BUFFER_SIZE_FRAMES;
|
||||||
//import std.stdio; writeln("filling ", ready);
|
//import std.stdio; writeln("filling ", ready);
|
||||||
fillData(buffer[0 .. ready * 2]);
|
fillData(buffer[0 .. ready * channels]);
|
||||||
if(playing) {
|
if(playing) {
|
||||||
snd_pcm_sframes_t written;
|
snd_pcm_sframes_t written;
|
||||||
auto data = buffer[0 .. ready * 2];
|
auto data = buffer[0 .. ready * channels];
|
||||||
|
|
||||||
while(data.length) {
|
while(data.length) {
|
||||||
written = snd_pcm_writei(handle, data.ptr, data.length / 2);
|
written = snd_pcm_writei(handle, data.ptr, data.length / channels);
|
||||||
if(written < 0) {
|
if(written < 0) {
|
||||||
written = snd_pcm_recover(handle, cast(int)written, 0);
|
written = snd_pcm_recover(handle, cast(int)written, 0);
|
||||||
if (written < 0) throw new AlsaException("pcm write", cast(int)written);
|
if (written < 0) throw new AlsaException("pcm write", cast(int)written);
|
||||||
}
|
}
|
||||||
data = data[written * 2 .. $];
|
data = data[written * channels .. $];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1562,7 +1584,7 @@ Pitch Bend Change. 0mmmmmmm This message is sent to indicate a change in the pit
|
||||||
|
|
||||||
version(ALSA)
|
version(ALSA)
|
||||||
// Opens the PCM device with default settings: stereo, 16 bit, 44.1 kHz, interleaved R/W.
|
// Opens the PCM device with default settings: stereo, 16 bit, 44.1 kHz, interleaved R/W.
|
||||||
snd_pcm_t* openAlsaPcm(snd_pcm_stream_t direction) {
|
snd_pcm_t* openAlsaPcm(snd_pcm_stream_t direction, int SampleRate, int channels) {
|
||||||
snd_pcm_t* handle;
|
snd_pcm_t* handle;
|
||||||
snd_pcm_hw_params_t* hwParams;
|
snd_pcm_hw_params_t* hwParams;
|
||||||
|
|
||||||
|
@ -1596,7 +1618,7 @@ snd_pcm_t* openAlsaPcm(snd_pcm_stream_t direction) {
|
||||||
|
|
||||||
assert(rate == SampleRate); // cheap me
|
assert(rate == SampleRate); // cheap me
|
||||||
|
|
||||||
if (auto err = snd_pcm_hw_params_set_channels(handle, hwParams, 2))
|
if (auto err = snd_pcm_hw_params_set_channels(handle, hwParams, channels))
|
||||||
throw new AlsaException("params channels", err);
|
throw new AlsaException("params channels", err);
|
||||||
|
|
||||||
uint periods = 2;
|
uint periods = 2;
|
||||||
|
|
Loading…
Reference in New Issue