mirror of
https://git.freebsd.org/ports.git
synced 2025-04-28 17:46:38 -04:00
203 lines
5.1 KiB
C++
203 lines
5.1 KiB
C++
--- media/audio/sndio/sndio_input.cc.orig 2023-07-24 14:27:53 UTC
|
|
+++ media/audio/sndio/sndio_input.cc
|
|
@@ -0,0 +1,200 @@
|
|
+// Copyright 2013 The Chromium Authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+#include "base/logging.h"
|
|
+#include "media/base/audio_timestamp_helper.h"
|
|
+#include "media/audio/sndio/audio_manager_sndio.h"
|
|
+#include "media/audio/audio_manager.h"
|
|
+#include "media/audio/sndio/sndio_input.h"
|
|
+
|
|
+namespace media {
|
|
+
|
|
+static const SampleFormat kSampleFormat = kSampleFormatS16;
|
|
+
|
|
+void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
|
|
+{
|
|
+ SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
|
|
+
|
|
+ self->hw_delay += delta;
|
|
+}
|
|
+
|
|
+void *SndioAudioInputStream::ThreadEntry(void *arg) {
|
|
+ SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
|
|
+
|
|
+ self->ThreadLoop();
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
|
|
+ const std::string& device_name,
|
|
+ const AudioParameters& params)
|
|
+ : manager(manager),
|
|
+ params(params),
|
|
+ audio_bus(AudioBus::Create(params)),
|
|
+ state(kClosed) {
|
|
+}
|
|
+
|
|
+SndioAudioInputStream::~SndioAudioInputStream() {
|
|
+ if (state != kClosed)
|
|
+ Close();
|
|
+}
|
|
+
|
|
+AudioInputStream::OpenOutcome SndioAudioInputStream::Open() {
|
|
+ struct sio_par par;
|
|
+ int sig;
|
|
+
|
|
+ if (state != kClosed)
|
|
+ return OpenOutcome::kFailed;
|
|
+
|
|
+ if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
|
|
+ params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
|
|
+ LOG(WARNING) << "Unsupported audio format.";
|
|
+ return OpenOutcome::kFailed;
|
|
+ }
|
|
+
|
|
+ sio_initpar(&par);
|
|
+ par.rate = params.sample_rate();
|
|
+ par.rchan = params.channels();
|
|
+ par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
|
|
+ par.bps = par.bits / 8;
|
|
+ par.sig = sig = par.bits != 8 ? 1 : 0;
|
|
+ par.le = SIO_LE_NATIVE;
|
|
+ par.appbufsz = params.frames_per_buffer();
|
|
+
|
|
+ hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
|
|
+
|
|
+ if (hdl == NULL) {
|
|
+ LOG(ERROR) << "Couldn't open audio device.";
|
|
+ return OpenOutcome::kFailed;
|
|
+ }
|
|
+
|
|
+ if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
|
|
+ LOG(ERROR) << "Couldn't set audio parameters.";
|
|
+ goto bad_close;
|
|
+ }
|
|
+
|
|
+ if (par.rate != (unsigned int)params.sample_rate() ||
|
|
+ par.rchan != (unsigned int)params.channels() ||
|
|
+ par.bits != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
|
|
+ par.sig != (unsigned int)sig ||
|
|
+ (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
|
|
+ (par.bits != par.bps * 8)) {
|
|
+ LOG(ERROR) << "Unsupported audio parameters.";
|
|
+ goto bad_close;
|
|
+ }
|
|
+ state = kStopped;
|
|
+ buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
|
|
+ sio_onmove(hdl, &OnMoveCallback, this);
|
|
+ return OpenOutcome::kSuccess;
|
|
+bad_close:
|
|
+ sio_close(hdl);
|
|
+ return OpenOutcome::kFailed;
|
|
+}
|
|
+
|
|
+void SndioAudioInputStream::Start(AudioInputCallback* cb) {
|
|
+
|
|
+ StartAgc();
|
|
+
|
|
+ state = kRunning;
|
|
+ hw_delay = 0;
|
|
+ callback = cb;
|
|
+ sio_start(hdl);
|
|
+ if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
|
|
+ LOG(ERROR) << "Failed to create real-time thread for recording.";
|
|
+ sio_stop(hdl);
|
|
+ state = kStopped;
|
|
+ }
|
|
+}
|
|
+
|
|
+void SndioAudioInputStream::Stop() {
|
|
+
|
|
+ if (state == kStopped)
|
|
+ return;
|
|
+
|
|
+ state = kStopWait;
|
|
+ pthread_join(thread, NULL);
|
|
+ sio_stop(hdl);
|
|
+ state = kStopped;
|
|
+
|
|
+ StopAgc();
|
|
+}
|
|
+
|
|
+void SndioAudioInputStream::Close() {
|
|
+
|
|
+ if (state == kClosed)
|
|
+ goto release;
|
|
+
|
|
+ if (state == kRunning)
|
|
+ Stop();
|
|
+
|
|
+ state = kClosed;
|
|
+ delete [] buffer;
|
|
+ sio_close(hdl);
|
|
+
|
|
+release:
|
|
+ manager->ReleaseInputStream(this);
|
|
+}
|
|
+
|
|
+double SndioAudioInputStream::GetMaxVolume() {
|
|
+ // Not supported
|
|
+ return 0.0;
|
|
+}
|
|
+
|
|
+void SndioAudioInputStream::SetVolume(double volume) {
|
|
+ // Not supported. Do nothing.
|
|
+}
|
|
+
|
|
+double SndioAudioInputStream::GetVolume() {
|
|
+ // Not supported.
|
|
+ return 0.0;
|
|
+}
|
|
+
|
|
+bool SndioAudioInputStream::IsMuted() {
|
|
+ // Not supported.
|
|
+ return false;
|
|
+}
|
|
+
|
|
+void SndioAudioInputStream::SetOutputDeviceForAec(
|
|
+ const std::string& output_device_id) {
|
|
+ // Not supported.
|
|
+}
|
|
+
|
|
+void SndioAudioInputStream::ThreadLoop(void) {
|
|
+ size_t todo, n;
|
|
+ char *data;
|
|
+ unsigned int nframes;
|
|
+ double normalized_volume = 0.0;
|
|
+
|
|
+ nframes = audio_bus->frames();
|
|
+
|
|
+ while (state == kRunning && !sio_eof(hdl)) {
|
|
+
|
|
+ GetAgcVolume(&normalized_volume);
|
|
+
|
|
+ // read one block
|
|
+ todo = nframes * params.GetBytesPerFrame(kSampleFormat);
|
|
+ data = buffer;
|
|
+ while (todo > 0) {
|
|
+ n = sio_read(hdl, data, todo);
|
|
+ if (n == 0)
|
|
+ return; // unrecoverable I/O error
|
|
+ todo -= n;
|
|
+ data += n;
|
|
+ }
|
|
+ hw_delay -= nframes;
|
|
+
|
|
+ // convert frames count to TimeDelta
|
|
+ const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
|
|
+ params.sample_rate());
|
|
+
|
|
+ // push into bus
|
|
+ audio_bus->FromInterleaved<SignedInt16SampleTypeTraits>(reinterpret_cast<int16_t*>(buffer), nframes);
|
|
+
|
|
+
|
|
+ // invoke callback
|
|
+ callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1., {});
|
|
+ }
|
|
+}
|
|
+
|
|
+} // namespace media
|