ConvertFilterPlugin.cxx 3.2 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2020 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * http://www.musicpd.org
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

20
#include "ConvertFilterPlugin.hxx"
21 22
#include "filter/Filter.hxx"
#include "filter/Prepared.hxx"
23
#include "pcm/AudioFormat.hxx"
24
#include "pcm/Convert.hxx"
25
#include "util/ConstBuffer.hxx"
26

27
#include <cassert>
28 29
#include <memory>

30
class ConvertFilter final : public Filter {
31 32 33 34
	/**
	 * The input audio format; PCM data is passed to the filter()
	 * method in this format.
	 */
35
	const AudioFormat in_audio_format;
36 37

	/**
38 39
	 * This object is only "open" if #in_audio_format !=
	 * #out_audio_format.
40
	 */
41
	std::unique_ptr<PcmConvert> state;
42

43
public:
Max Kellermann's avatar
Max Kellermann committed
44
	explicit ConvertFilter(const AudioFormat &audio_format);
45

46
	void Set(const AudioFormat &_out_audio_format);
47

48
	void Reset() noexcept override {
49 50
		if (state)
			state->Reset();
51 52
	}

53
	ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
54 55

	ConstBuffer<void> Flush() override {
56 57
		return state
			? state->Flush()
58
			: nullptr;
59
	}
60 61
};

62 63
class PreparedConvertFilter final : public PreparedFilter {
public:
64
	std::unique_ptr<Filter> Open(AudioFormat &af) override;
65 66
};

67 68
void
ConvertFilter::Set(const AudioFormat &_out_audio_format)
69 70 71 72 73
{
	assert(_out_audio_format.IsValid());

	if (_out_audio_format == out_audio_format)
		/* no change */
74
		return;
75

76
	if (state) {
77
		out_audio_format = in_audio_format;
78
		state.reset();
79 80 81 82
	}

	if (_out_audio_format == in_audio_format)
		/* optimized special case: no-op */
83
		return;
84

85 86
	state = std::make_unique<PcmConvert>(in_audio_format,
					     _out_audio_format);
87 88 89 90

	out_audio_format = _out_audio_format;
}

91 92
ConvertFilter::ConvertFilter(const AudioFormat &audio_format)
	:Filter(audio_format), in_audio_format(audio_format)
93
{
94
	assert(in_audio_format.IsValid());
95
}
96

97
std::unique_ptr<Filter>
98
PreparedConvertFilter::Open(AudioFormat &audio_format)
99 100
{
	assert(audio_format.IsValid());
101

102
	return std::make_unique<ConvertFilter>(audio_format);
103 104
}

105
ConstBuffer<void>
106
ConvertFilter::FilterPCM(ConstBuffer<void> src)
107
{
108 109
	return state
		? state->Convert(src)
110
		/* optimized special case: no-op */
111
		: src;
112 113
}

114
std::unique_ptr<PreparedFilter>
115 116
convert_filter_prepare() noexcept
{
117
	return std::make_unique<PreparedConvertFilter>();
118 119
}

120 121
Filter *
convert_filter_new(const AudioFormat in_audio_format,
122
		   const AudioFormat out_audio_format)
123
{
124 125 126
	std::unique_ptr<ConvertFilter> filter(new ConvertFilter(in_audio_format));
	filter->Set(out_audio_format);
	return filter.release();
127 128
}

129 130
void
convert_filter_set(Filter *_filter, AudioFormat out_audio_format)
131
{
Max Kellermann's avatar
Max Kellermann committed
132
	auto *filter = (ConvertFilter *)_filter;
133

134
	filter->Set(out_audio_format);
135
}