coast_audio 0.0.1 coast_audio: ^0.0.1 copied to clipboard
A cross-platform audio processing library written in dart
Overview #
coast_audio
is a high performance audio processing library written in dart.
This package aims to provide low-level audio functionalities.
Audio Format #
AudioFormat
contains sample rate, channels, sample format information.
You may usually use this class to allocate audio buffer or provide information to audio nodes.
Audio Processing #
You can use AudioNode
subclasses to produce or process an audio buffer.
There are two kinds of nodes are available.
- Data Source Node
- produces the audio data and write to buffer
- usually extends the
DataSourceNode
abstract class
- Processor Node
- manipulate, consume, and/or passthrough the audio buffer to the connected node
- usually extends the
SingleInOutNode
withProcessorNodeMixin
.
For example, FunctionNode
can produce wave data based on the supplied function, which extends the DataSourceNode
.
It has one outputBus
so you can read audio data from it.
Below code generates 48000hz stereo sine wave.
import 'package:coast_audio/coast_audio.dart';
const format = AudioFormat(sampleRate: 48000, channels: 2); // sampleFormat is float32 by default.
final functionNode = FunctionNode(
function: const SineFunction(),
frequency: 440,
);
final buffer = AllocatedFrameBuffer(
frames: 1024,
format: format,
);
// Read to the buffer and returns the number of frames produces
final int framesRead = functionNode.outputBus.read(buffer);
// Limit the buffer size to framesRead and acquire float list data
buffer.limit(framesRead).acquireFloatListView((audioSampleList) {
// Do whatever you want!
});
// Dispose the buffer.
buffer.dispose();
coast_audio
has various kinds of built-in nodes
- GraphNode
- DecoderNode
- ConverterNode
- FunctionNode
- MixerNode
- VolumeNode
- etc
Each node has one or more busses to connect with other nodes.
GraphNode #
To build your own audio graph, use the GraphNode
class.
GraphNode
has connect
and connectEndpoint
methods to connect between node's bus.
Example: Wave Volume Control
This example generates sine wave and applies volume 50%.
final graphNode = GraphNode();
final sineNode = FunctionNode(function: const SineFunction(), format: format, frequency: 440);
final sineVolumeNode = VolumeNode(volume: 0.5);
// FunctionNode(Sine) -> VolumeNode
graphNode.connect(sineNode.outputBus, sineVolumeNode.inputBus);
// VolumeNode -> GraphNode's Endpoint
graphNode.connectEndpoint(sineVolumeNode.outputBus);
// Read to your buffer. (Returned value has how many frames written to your buffer)
final framesRead = graphNode.outputBus.read(buffer);
final readBuffer = buffer.limit(framesRead);
Example: Wave mixing and write to file
See the example code.
Audio Buffer #
FrameBuffer #
By using FrameBuffer
subclasses, you can manage audio buffers easily.
You usually use the AllocatedFrameBuffer
subclass.
AllocatedFrameBuffer
have lock
and unlock
methods to access the RawFrameBuffer
which contains the pointer to raw audio data.
final buffer = AllocatedFrameBuffer(frames: 1024, format: format);
final rawBuffer = buffer.lock();
try {
// Use the rawBuffer.pBuffer to access the raw audio data.
// Or you can call rawBuffer.asFloatListView() to acquire the view of list data.
} finally {
rawBuffer.unlock();
}
buffer.dispose();
Or you can use acquireBuffer
to lock & unlock audio buffer automatically.
buffer.acquireBuffer((rawBuffer) {
// buffer will be unlocked when the callback method is finished.
});
RawFrameBuffer
have offset
and limit
methods to retrieve the sub view of RawFrameBuffer
.
final buffer = AllocatedFrameBuffer(frames: 1024, format: format);
final rawBuffer = buffer.lock();
final subBuffer1 = rawBuffer.limit(128); // Takes first 128 frames.
final subBuffer2 = rawBuffer.offset(128); // Skips first 128 frames.
rawBuffer.unlock();
buffer.dispose(); // subBuffer1 and subBuffer2 will invalidated too.
RingBuffer #
coast_audio
provides ring buffer implementations.
You can use the FrameRingBuffer
to manage audio frames, or use the RingBuffer
to manage data in binary format.
Audio Decoder #
When you want to read audio data from a file, use the AudioFileDataSource
class and pass it to the AudioDecoder
subclasses.
Currently, this package only provides WavAudioDecoder
which can read the wav file from the data source.
final dataSource = AudioFileDataSource(file: File('test.wav'), mode: FileMode.read);
final decoder = WavAudioDecoder(dataSource: dataSource);
final buffer = AllocatedFrameBuffer(frames: 512, format: decoder.format);
buffer.acquireBuffer((buffer) {
final result = decoder.decode(destination: buffer);
final readBuffer = buffer.limit(result.frames);
// `readBuffer` is now contains decoded audio data.
});
buffer.dispose();
If you want to read a mp3 or flac file, use the coast_audio_miniaudio package instead.
It has MabAudioDecoder class to read audio data from the file.
Then, you can initialize the DecoderNode
to supply audio data to your audio graph.