Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,28 @@ emscripten_test:

[doc("serve project for WASM")]
emscripten_serve:
#python3 -m http.server -d .
python3 tools/serve.py -p 8000 -d .
#uv run python -m http.server -d .
uv run python tools/serve.py -p 8000 -d .

[working-directory: 'python']
python_wheel:
python -m build --wheel
uv pip install build
uv run python -m build --wheel
@just python_install
@just python_test

[working-directory: 'python']
python_install:
python -m pip install --force-reinstall dist/yup-*.whl
uv pip install --force-reinstall dist/yup-*.whl

[working-directory: 'python']
python_uninstall:
python -m pip uninstall -y yup
uv pip uninstall -y yup

[working-directory: 'python']
python_test *TEST_OPTS:
python -m pytest -s {{TEST_OPTS}}
uv sync --group test
uv run --group test python -m pytest -s {{TEST_OPTS}}

[working-directory: 'cmake/tools/shader_bundler']
shader_bundler *COMPILE_ARGS:
Expand Down
6 changes: 6 additions & 0 deletions modules/yup_animation/renderer/yup_AnimationFrameExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ AnimationFrameExporter::AnimationFrameExporter (GraphicsContext& ctx)

AnimationFrameExporter::~AnimationFrameExporter() = default;

//==============================================================================
Size<int> AnimationFrameExporter::resolveTargetSize (const Animation& anim, Size<int> requested)
{
if (requested.getWidth() > 0 && requested.getHeight() > 0)
Expand All @@ -41,6 +42,7 @@ Size<int> AnimationFrameExporter::resolveTargetSize (const Animation& anim, Size
return { (int) native.getWidth(), (int) native.getHeight() };
}

//==============================================================================
Image AnimationFrameExporter::renderFrame (const Animation& anim,
float frameNo,
Size<int> targetSize)
Expand All @@ -63,6 +65,7 @@ Image AnimationFrameExporter::renderFrame (const Animation& anim,
return img;
}

//==============================================================================
ResultValue<std::vector<Image>> AnimationFrameExporter::renderAllFrames (const Animation& anim, Size<int> targetSize)
{
if (! anim.isValid())
Expand All @@ -85,6 +88,8 @@ ResultValue<std::vector<Image>> AnimationFrameExporter::renderAllFrames (const A
return makeResultValueOk (std::move (frames));
}

//==============================================================================
#if YUP_IMAGE_FORMAT_GIF
Result AnimationFrameExporter::exportToGif (const Animation& anim,
const File& destination,
Size<int> targetSize,
Expand Down Expand Up @@ -165,5 +170,6 @@ Result AnimationFrameExporter::exportToGif (const std::vector<Image>& frames,

return Result::ok();
}
#endif

} // namespace yup
2 changes: 2 additions & 0 deletions modules/yup_animation/renderer/yup_AnimationFrameExporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class YUP_API AnimationFrameExporter
[[nodiscard]] ResultValue<std::vector<Image>> renderAllFrames (const Animation& anim,
Size<int> targetSize = {});

#if YUP_IMAGE_FORMAT_GIF
//==============================================================================
/** Exports the animation to an animated GIF file.

Expand Down Expand Up @@ -119,6 +120,7 @@ class YUP_API AnimationFrameExporter
float frameRate,
const File& destination,
int qualityLevel = 80);
#endif

private:
static Size<int> resolveTargetSize (const Animation& anim, Size<int> requested);
Expand Down
2 changes: 1 addition & 1 deletion modules/yup_audio_devices/yup_audio_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
license: ISC

dependencies: yup_audio_basics yup_events
optionalDeps: yup_graphics
optionalDeps: yup_graphics yup_audio_formats
appleFrameworks: CoreAudio CoreMIDI AudioToolbox
iosFrameworks: AVFoundation
iosSimFrameworks: AVFoundation
Expand Down
170 changes: 170 additions & 0 deletions modules/yup_audio_formats/sources/yup_AudioFormatReaderSource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
==============================================================================

This file is part of the YUP library.
Copyright (c) 2026 - kunitoki@gmail.com

YUP is an open source library subject to open-source licensing.

The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.

YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.

==============================================================================
*/

namespace yup
{

//==============================================================================
AudioFormatReaderSource::AudioFormatReaderSource (AudioFormatReader* sourceReader,
bool deleteReaderWhenThisIsDeleted)
: reader (sourceReader)
, deleteReader (deleteReaderWhenThisIsDeleted)
{
// Allow null reader — source produces silence
}

AudioFormatReaderSource::AudioFormatReaderSource (std::unique_ptr<AudioFormatReader> sourceReader)
: ownedReader (std::move (sourceReader))
, reader (ownedReader.get())
, deleteReader (false)
{
}

AudioFormatReaderSource::~AudioFormatReaderSource()
{
if (reader != nullptr && deleteReader)
delete reader;
}

//==============================================================================
int64 AudioFormatReaderSource::getTotalLength() const
{
if (reader == nullptr)
return 0;
return reader->lengthInSamples;
}

void AudioFormatReaderSource::setNextReadPosition (int64 newPosition)
{
if (newPosition < 0)
newPosition = 0;

nextReadPosition = newPosition;
}

int64 AudioFormatReaderSource::getNextReadPosition() const
{
return nextReadPosition;
}

bool AudioFormatReaderSource::isLooping() const
{
return looping;
}

void AudioFormatReaderSource::setLooping (bool shouldLoop)
{
looping = shouldLoop;
}

//==============================================================================
void AudioFormatReaderSource::prepareToPlay (int /*samplesPerBlockExpected*/,
double /*sampleRate*/)
{
}

void AudioFormatReaderSource::releaseResources()
{
}

void AudioFormatReaderSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
if (reader == nullptr)
{
bufferToFill.clearActiveBufferRegion();
return;
}

const auto totalLength = getTotalLength();

if (totalLength > 0)
{
auto samplesAvailable = totalLength - nextReadPosition;

if (samplesAvailable < bufferToFill.numSamples)
{
if (looping)
{
auto samplesNeeded = bufferToFill.numSamples;
auto firstChunk = static_cast<int> (samplesAvailable);
auto secondChunk = samplesNeeded - firstChunk;

// Read first chunk from the end of the file
if (firstChunk > 0)
{
reader->read (bufferToFill.buffer,
bufferToFill.startSample,
firstChunk,
nextReadPosition,
true,
true);
}

// Read second chunk from the beginning of the file
if (secondChunk > 0)
{
reader->read (bufferToFill.buffer,
bufferToFill.startSample + firstChunk,
secondChunk,
0,
true,
true);
}

nextReadPosition = secondChunk;
}
else
{
// Read what's left and clear the rest
auto numToRead = static_cast<int> (samplesAvailable);

reader->read (bufferToFill.buffer,
bufferToFill.startSample,
numToRead,
nextReadPosition,
true,
true);

bufferToFill.buffer->clear (bufferToFill.startSample + numToRead,
bufferToFill.numSamples - numToRead);

nextReadPosition = totalLength;
}
}
else
{
reader->read (bufferToFill.buffer,
bufferToFill.startSample,
bufferToFill.numSamples,
nextReadPosition,
true,
true);

nextReadPosition += bufferToFill.numSamples;
}
}
else
{
bufferToFill.clearActiveBufferRegion();
}
}

} // namespace yup
98 changes: 98 additions & 0 deletions modules/yup_audio_formats/sources/yup_AudioFormatReaderSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
==============================================================================

This file is part of the YUP library.
Copyright (c) 2026 - kunitoki@gmail.com

YUP is an open source library subject to open-source licensing.

The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.

YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.

==============================================================================
*/

namespace yup
{

//==============================================================================
/**
A PositionableAudioSource that reads from an AudioFormatReader.

This class wraps an AudioFormatReader, turning it into a PositionableAudioSource
that can be used with AudioTransportSource for playback of audio files.

This is the simplest way to read from an audio file: create an AudioFormatReader
for the file, wrap it in an AudioFormatReaderSource, pass it to an
AudioTransportSource, and play.

@see AudioFormatReader, AudioTransportSource, PositionableAudioSource

@tags{Audio}
*/
class YUP_API AudioFormatReaderSource : public PositionableAudioSource
{
public:
//==============================================================================
/** Creates an AudioFormatReaderSource from an AudioFormatReader.

@param sourceReader the reader to use as the source. The
AudioFormatReaderSource will take ownership
of this reader and delete it when no longer needed.
@param deleteReaderWhenThisIsDeleted if true, the sourceReader will be deleted
when this object is destroyed
*/
AudioFormatReaderSource (AudioFormatReader* sourceReader,
bool deleteReaderWhenThisIsDeleted);

/** Creates an AudioFormatReaderSource from a unique_ptr.
Takes ownership of the reader.
*/
explicit AudioFormatReaderSource (std::unique_ptr<AudioFormatReader> sourceReader);

/** Destructor. */
~AudioFormatReaderSource() override;

//==============================================================================
/** Returns the AudioFormatReader being used as the source. */
AudioFormatReader* getAudioFormatReader() const noexcept { return reader; }

//==============================================================================
/** @internal */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
/** @internal */
void releaseResources() override;
/** @internal */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override;

//==============================================================================
/** @internal */
void setNextReadPosition (int64 newPosition) override;
/** @internal */
int64 getNextReadPosition() const override;
/** @internal */
int64 getTotalLength() const override;
/** @internal */
bool isLooping() const override;
/** @internal */
void setLooping (bool shouldLoop) override;

private:
//==============================================================================
std::unique_ptr<AudioFormatReader> ownedReader;
AudioFormatReader* reader = nullptr;
bool deleteReader = false;
int64 nextReadPosition = 0;
bool looping = false;

YUP_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioFormatReaderSource)
};

} // namespace yup
1 change: 1 addition & 0 deletions modules/yup_audio_formats/yup_audio_formats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
#include "format/yup_AudioFormatReader.cpp"
#include "format/yup_AudioFormatWriter.cpp"
#include "common/yup_AudioFormatManager.cpp"
#include "sources/yup_AudioFormatReaderSource.cpp"

//==============================================================================

Expand Down
1 change: 1 addition & 0 deletions modules/yup_audio_formats/yup_audio_formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
#include "format/yup_AudioFormatReader.h"
#include "format/yup_AudioFormatWriter.h"
#include "common/yup_AudioFormatManager.h"
#include "sources/yup_AudioFormatReaderSource.h"

//==============================================================================

Expand Down
Loading
Loading