File:  [Isaki's NoNo m68k/m88k emulator] / nono / host / sounddriver_alsa.cpp
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:02 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2025 nono project
// Licensed under nono-license.txt
//

//
// サウンドの ALSA ドライバ
//

#include "sounddriver_alsa.h"
#include "config.h"
#include "mainapp.h"
#include "sound.h"
#include <alsa/asoundlib.h>

// コンストラクタ
SoundDriverALSA::SoundDriverALSA(HostDevice *hostdev_)
	: inherited(hostdev_, "alsa")
{
}

// デストラクタ
SoundDriverALSA::~SoundDriverALSA()
{
	Close();
}

bool
SoundDriverALSA::InitDriver(bool startup)
{
	snd_pcm_hw_params_t *params;
	bool rv = false;

	if (inherited::InitDriver(startup) == false) {
		return false;
	}

	const ConfigItem& item = gConfig->Find("hostsound-alsa-device");
	device = item.AsString();

	if (snd_pcm_open(&pcm, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0) < 0) {
		warnx("%s: snd_pcm_open(%s) failed", __method__, device.c_str());
		return false;
	}

	uint period = freq * Sound::BLK_TSEC / 1_sec;

	snd_pcm_hw_params_malloc(&params);
	snd_pcm_hw_params_any(pcm, params);
	snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16);//HostEndian
	snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	snd_pcm_hw_params_set_channels(pcm, params, Sound::NCHAN);
	snd_pcm_hw_params_set_rate(pcm, params, freq, 0);
	snd_pcm_hw_params_set_period_size(pcm, params, period, 0);
	snd_pcm_hw_params_set_buffer_size(pcm, params, period * 4);
	if (snd_pcm_hw_params(pcm, params) < 0) {
		warnx("%s: snd_pcm_hw_params() failed", __method__);
		goto done;
	}

	rv = true;
 done:
	snd_pcm_hw_params_free(params);
	return rv;
}

// ブロック書き出し
void
SoundDriverALSA::Write(const int16 *blk)
{
	size_t frames_per_blk = blkbytes / Sound::FRAME_BYTES;

	// ALSA では書き込みはフレーム単位で、一度に行う志向。
	snd_pcm_prepare(pcm);
	auto r = snd_pcm_writei(pcm, blk, frames_per_blk);
	if (r < 0) {
		warnx("%s: snd_pcm_writei() failed: %d", __method__, (int)r);
		snd_pcm_prepare(pcm);
		if (r == -EPIPE) {
			// 一度だけ再試行してみる?
			snd_pcm_writei(pcm, blk, frames_per_blk);
		}
	}
}

void
SoundDriverALSA::Close()
{
	snd_pcm_drain(pcm);
	snd_pcm_close(pcm);
}

void
SoundDriverALSA::MonitorScreenMD(TextScreen& screen, int y)
{
	screen.Print(0, y, "Device:           %s", device.c_str());
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.