-
Notifications
You must be signed in to change notification settings - Fork 26
RSDK-12151 Audio Out Component Type #495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 10 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
bb3da91
start audio out
oliviamiller 84bbaa2
improve tests
oliviamiller 1655c8e
cmake
oliviamiller 394d8db
clean up
oliviamiller 6f29f00
lint
oliviamiller 31e7ff2
lint
oliviamiller 3cf34e1
lint mock
oliviamiller 28f9686
Merge branch 'main' into audioout
oliviamiller 2b3f253
clean up
oliviamiller b1f2aa0
add code sample
oliviamiller 879b07a
use boost optional
oliviamiller c6fca79
lint
oliviamiller d95a1de
merge
oliviamiller d3c4c0e
add back info == operator
oliviamiller File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| #include <viam/sdk/common/audio.hpp> | ||
|
|
||
| #include <fstream> | ||
| #include <stdexcept> | ||
| #include <tuple> | ||
|
|
||
| namespace viam { | ||
| namespace sdk { | ||
|
|
||
| namespace { | ||
| template <typename T> | ||
| void write_value(std::ofstream& out, const T& value) { | ||
| out.write(reinterpret_cast<const char*>(&value), sizeof(value)); | ||
| } | ||
| } // anonymous namespace | ||
|
|
||
| bool operator==(const audio_properties& lhs, const audio_properties& rhs) { | ||
| return std::tie(lhs.supported_codecs, lhs.sample_rate_hz, lhs.num_channels) == | ||
| std::tie(rhs.supported_codecs, rhs.sample_rate_hz, rhs.num_channels); | ||
| } | ||
|
|
||
| bool operator==(const audio_info& lhs, const audio_info& rhs) { | ||
| return std::tie(lhs.codec, lhs.sample_rate_hz, lhs.num_channels) == | ||
| std::tie(rhs.codec, rhs.sample_rate_hz, rhs.num_channels); | ||
| } | ||
|
|
||
| uint16_t get_bits_per_sample(const std::string& codec) { | ||
| if (codec == audio_codecs::PCM_16) { | ||
| return 16; | ||
| } | ||
| if (codec == audio_codecs::PCM_32 || codec == audio_codecs::PCM_32_FLOAT) { | ||
| return 32; | ||
| } | ||
| throw std::runtime_error("Unsupported codec for WAV file: " + codec); | ||
| } | ||
|
|
||
| void write_wav_file(const std::string& filename, | ||
| const std::vector<uint8_t>& audio_data, | ||
| const std::string& codec, | ||
| uint32_t sample_rate_hz, | ||
| uint16_t num_channels) { | ||
| std::ofstream outfile(filename, std::ios::binary); | ||
| if (!outfile.is_open()) { | ||
| throw std::runtime_error("Failed to open file for writing: " + filename); | ||
| } | ||
|
|
||
| const uint16_t bits_per_sample = get_bits_per_sample(codec); | ||
| const uint32_t data_size = audio_data.size(); | ||
| const uint32_t byte_rate = sample_rate_hz * num_channels * (bits_per_sample / 8); | ||
| const uint16_t block_align = num_channels * (bits_per_sample / 8); | ||
|
|
||
| outfile.write("RIFF", 4); | ||
| const uint32_t chunk_size = 36 + data_size; | ||
| write_value(outfile, chunk_size); | ||
| outfile.write("WAVE", 4); | ||
|
|
||
| outfile.write("fmt ", 4); | ||
| const uint32_t subchunk1_size = 16; | ||
| write_value(outfile, subchunk1_size); | ||
| const uint16_t audio_format = 1; | ||
| write_value(outfile, audio_format); | ||
| write_value(outfile, num_channels); | ||
| write_value(outfile, sample_rate_hz); | ||
| write_value(outfile, byte_rate); | ||
| write_value(outfile, block_align); | ||
| write_value(outfile, bits_per_sample); | ||
|
|
||
| outfile.write("data", 4); | ||
| write_value(outfile, data_size); | ||
| outfile.write(reinterpret_cast<const char*>(audio_data.data()), data_size); | ||
|
|
||
| outfile.close(); | ||
| } | ||
|
|
||
| } // namespace sdk | ||
| } // namespace viam |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| namespace viam { | ||
| namespace sdk { | ||
|
|
||
| /// @brief Common audio codecs | ||
| namespace audio_codecs { | ||
| constexpr const char* PCM_16 = "pcm16"; | ||
| constexpr const char* PCM_32 = "pcm32"; | ||
| constexpr const char* PCM_32_FLOAT = "pcm32_float"; | ||
| constexpr const char* MP3 = "mp3"; | ||
| constexpr const char* AAC = "aac"; | ||
| constexpr const char* OPUS = "opus"; | ||
| constexpr const char* FLAC = "flac"; | ||
| } // namespace audio_codecs | ||
|
|
||
| /// @struct audio_properties | ||
| /// @brief Properties of an audio component (input or output) | ||
| struct audio_properties { | ||
| std::vector<std::string> supported_codecs; | ||
| int sample_rate_hz; | ||
| int num_channels; | ||
| }; | ||
|
|
||
| /// @struct audio_info | ||
| /// @brief Information about a piece of audio data | ||
| struct audio_info { | ||
| std::string codec; | ||
| int sample_rate_hz; | ||
| int num_channels; | ||
| }; | ||
|
|
||
| /// @brief Equality operator for properties | ||
| bool operator==(const audio_properties& lhs, const audio_properties& rhs); | ||
|
|
||
| /// @brief Equality operator for audio_info | ||
| bool operator==(const audio_info& lhs, const audio_info& rhs); | ||
|
|
||
| uint16_t get_bits_per_sample(const std::string& codec); | ||
|
|
||
| void write_wav_file(const std::string& filename, | ||
| const std::vector<uint8_t>& audio_data, | ||
| const std::string& codec, | ||
| uint32_t sample_rate_hz, | ||
| uint16_t num_channels); | ||
|
|
||
| } // namespace sdk | ||
| } // namespace viam |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #include <viam/sdk/components/audio_out.hpp> | ||
|
|
||
| #include <viam/sdk/common/audio.hpp> | ||
| #include <viam/sdk/common/exception.hpp> | ||
| #include <viam/sdk/common/utils.hpp> | ||
| #include <viam/sdk/resource/resource.hpp> | ||
|
|
||
| namespace viam { | ||
| namespace sdk { | ||
|
|
||
| API AudioOut::api() const { | ||
| return API::get<AudioOut>(); | ||
| } | ||
|
|
||
| API API::traits<AudioOut>::api() { | ||
| return {kRDK, kComponent, "audio_out"}; | ||
| } | ||
|
|
||
| AudioOut::AudioOut(std::string name) : Component(std::move(name)) {} | ||
|
|
||
| } // namespace sdk | ||
| } // namespace viam |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| /// @file components/audio_out.hpp | ||
| /// | ||
| /// @brief Defines an `AudioOut` component. | ||
| #pragma once | ||
|
|
||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include <viam/sdk/common/audio.hpp> | ||
| #include <viam/sdk/common/proto_value.hpp> | ||
| #include <viam/sdk/common/utils.hpp> | ||
| #include <viam/sdk/config/resource.hpp> | ||
|
|
||
| namespace viam { | ||
| namespace sdk { | ||
|
|
||
| /// @defgroup AudioOut Classes related to the AudioOut component. | ||
|
|
||
| /// @class AudioOut audio_out.hpp "components/audio_out.hpp" | ||
| /// @brief An `AudioOut` is a device that can output audio. | ||
| /// @ingroup AudioOut | ||
| /// | ||
| /// This acts as an abstract parent class to be inherited from by any drivers representing | ||
| /// specific AudioOut implementations. This class cannot be used on its own. | ||
| class AudioOut : public Component { | ||
| public: | ||
| using audio_info = viam::sdk::audio_info; | ||
|
|
||
| /// @brief Play audio data | ||
| /// @param audio_data The audio data to play as bytes | ||
| /// @param info Optional info about the audio_data (codec, sample rate, channels). Required for | ||
| /// raw PCM data, pass nullptr if not needed. | ||
| inline void play(std::vector<uint8_t> const& audio_data, | ||
| std::shared_ptr<audio_info> info = nullptr) { | ||
| return play(audio_data, info, {}); | ||
| } | ||
|
|
||
| /// @brief Play audio through the audioout component | ||
| /// @param audio_data The audio data to play | ||
| /// @param info Optional info about the audio_data (codec, sample rate, channels). Required for | ||
| /// raw PCM data, pass nullptr if not needed. | ||
| /// @param extra Any additional arguments to the method | ||
| virtual void play(std::vector<uint8_t> const& audio_data, | ||
| std::shared_ptr<audio_info> info, | ||
| const ProtoStruct& extra) = 0; | ||
|
|
||
| /// @brief Returns properties of the audio out device (supported codecs, sample rate, number of | ||
| /// channels) | ||
| inline audio_properties get_properties() { | ||
| return get_properties({}); | ||
| } | ||
|
|
||
| /// @brief Returns properties of the audio out device (supported codecs, sample rate, number of | ||
| /// channels) | ||
| /// @param extra Any additional arguments to the method | ||
| virtual audio_properties get_properties(const ProtoStruct& extra) = 0; | ||
|
|
||
| /// @brief Send/receive arbitrary commands to the resource. | ||
| /// @param command the command to execute. | ||
| /// @return The result of the executed command. | ||
| virtual ProtoStruct do_command(const ProtoStruct& command) = 0; | ||
|
|
||
| // @brief Returns `GeometryConfig`s associated with the calling audioout. | ||
| /// @return The requested `GeometryConfig`s associated with the component. | ||
| inline std::vector<GeometryConfig> get_geometries() { | ||
| return get_geometries({}); | ||
| } | ||
|
|
||
| /// @brief Returns `GeometryConfig`s associated with the calling audioout. | ||
| /// @param extra Any additional arguments to the method. | ||
| /// @return The requested `GeometryConfig`s associated with the component. | ||
| virtual std::vector<GeometryConfig> get_geometries(const ProtoStruct& extra) = 0; | ||
|
|
||
| API api() const override; | ||
|
|
||
| protected: | ||
| explicit AudioOut(std::string name); | ||
| }; | ||
|
|
||
| template <> | ||
| struct API::traits<AudioOut> { | ||
| static API api(); | ||
| }; | ||
|
|
||
| } // namespace sdk | ||
| } // namespace viam | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made info a shared pointer so it could be optional by passing a nullptr, unsure if thats the best way to handle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's use
boost::optionalfor this sort of thing