Skip to content

Commit a2b37e3

Browse files
committed
fix header order for mem
1 parent d707147 commit a2b37e3

File tree

6 files changed

+125
-2
lines changed

6 files changed

+125
-2
lines changed

Resources/test_memory_share.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ set -e
77

88
# Check multiple possible locations for shared memory files
99
TEMP_DIRS=(
10+
"$HOME/Library/Group Containers/group.com.mach1.spatial.shared/Library/Caches/M1-Panner"
1011
"$HOME/Library/Caches/M1-Panner"
12+
"/tmp/M1-Panner"
1113
"/tmp"
1214
"$HOME/Library/Caches"
1315
)
@@ -186,6 +188,10 @@ struct SharedMemoryHeader {
186188
// Consumer management
187189
volatile uint32_t consumerCount;
188190
volatile uint32_t consumerIds[16];
191+
// Bidirectional communication - Control messages from consumers back to producer
192+
volatile uint32_t controlMessageCount;
193+
volatile uint32_t controlReadIndex;
194+
volatile uint32_t controlWriteIndex;
189195
};
190196
191197
struct QueuedBuffer {

Resources/test_memory_timeline_consumer.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ struct SharedMemoryHeader {
8888
// Consumer management
8989
volatile uint32_t consumerCount;
9090
volatile uint32_t consumerIds[16];
91+
// Bidirectional communication - Control messages from consumers back to producer
92+
volatile uint32_t controlMessageCount;
93+
volatile uint32_t controlReadIndex;
94+
volatile uint32_t controlWriteIndex;
9195
};
9296
9397
struct QueuedBuffer {

Source/M1MemoryShare.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,16 @@ class M1MemoryShare
5050
// Consumer management
5151
volatile uint32_t consumerCount; // Number of registered consumers
5252
volatile uint32_t consumerIds[16]; // Consumer IDs (max 16 consumers)
53+
54+
// Bidirectional communication - Control messages from consumers back to producer
55+
volatile uint32_t controlMessageCount; // Number of pending control messages
56+
volatile uint32_t controlReadIndex; // Read index for control messages
57+
volatile uint32_t controlWriteIndex; // Write index for control messages
5358

5459
SharedMemoryHeader() : writeIndex(0), readIndex(0), dataSize(0), hasData(false),
5560
bufferSize(0), sampleRate(0), numChannels(0), samplesPerBlock(0),
5661
queueSize(0), maxQueueSize(8), nextSequenceNumber(0), nextBufferId(1),
57-
consumerCount(0)
62+
consumerCount(0), controlMessageCount(0), controlReadIndex(0), controlWriteIndex(0)
5863
{
5964
std::memset(name, 0, sizeof(name));
6065
std::memset(const_cast<uint32_t*>(consumerIds), 0, sizeof(consumerIds));

Source/PluginProcessor.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,13 @@ void M1PannerAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBloc
448448
postAlert(alert);
449449
}
450450
}
451+
452+
// Initialize memory sharing if in external spatial mixer mode
453+
// This ensures the memory file is created even before audio starts playing
454+
if (external_spatialmixer_active && !m_memoryShareInitialized)
455+
{
456+
initializeMemorySharing();
457+
}
451458
}
452459

453460
void M1PannerAudioProcessor::releaseResources()
@@ -1171,6 +1178,13 @@ void M1PannerAudioProcessor::timerCallback()
11711178
// Added if we need to move the OSC stuff from the processorblock
11721179
pannerOSC->update(); // test for connection
11731180

1181+
// Update memory sharing with current parameters (even when audio isn't playing)
1182+
// This ensures parameter changes are visible to the helper immediately
1183+
if (external_spatialmixer_active && m_memoryShareInitialized && m_memoryShare && m_memoryShare->isValid())
1184+
{
1185+
updateMemorySharingParametersOnly();
1186+
}
1187+
11741188
// ON-DEMAND SERVICE INTEGRATION: Periodic health check for helper service
11751189
// Check every ~10 seconds (timer runs every 200ms, so check every 50 calls)
11761190
static int healthCheckCounter = 0;
@@ -1593,12 +1607,105 @@ void M1PannerAudioProcessor::updateMemorySharing(const juce::AudioBuffer<float>&
15931607

15941608
// Add state and color info
15951609
parameters.addInt(M1PannerParameterIDs::STATE, pannerSettings.state.load());
1610+
parameters.addInt(M1PannerParameterIDs::PORT, pannerSettings.port);
1611+
1612+
// Add color info
1613+
parameters.addInt(M1PannerParameterIDs::COLOR_R, static_cast<int32_t>(pannerSettings.color.r.load()));
1614+
parameters.addInt(M1PannerParameterIDs::COLOR_G, static_cast<int32_t>(pannerSettings.color.g.load()));
1615+
parameters.addInt(M1PannerParameterIDs::COLOR_B, static_cast<int32_t>(pannerSettings.color.b.load()));
1616+
parameters.addInt(M1PannerParameterIDs::COLOR_A, static_cast<int32_t>(pannerSettings.color.a.load()));
1617+
1618+
// Add display name (track name from host) - cache it from track_properties
1619+
// Note: track_properties is updated by host via updateTrackProperties()
1620+
std::string displayName;
1621+
if (track_properties.name.has_value() && !track_properties.name->isEmpty())
1622+
{
1623+
displayName = track_properties.name->toStdString();
1624+
}
1625+
else
1626+
{
1627+
// Fallback: use a generated name with the port/instance ID
1628+
displayName = "M1-Panner (" + std::to_string(pannerSettings.port) + ")";
1629+
}
1630+
parameters.addString(M1PannerParameterIDs::DISPLAY_NAME, displayName);
15961631

15971632
// Write audio buffer with generic parameters
15981633
// Note: writeAudioBufferWithGenericParameters should be RT-safe internally
15991634
m_memoryShare->writeAudioBufferWithGenericParameters(inputBuffer, parameters, dawTimestamp, playheadPosition, isPlaying, true);
16001635
}
16011636

1637+
void M1PannerAudioProcessor::updateMemorySharingParametersOnly()
1638+
{
1639+
if (!m_memoryShare || !m_memoryShare->isValid())
1640+
{
1641+
return;
1642+
}
1643+
1644+
// Get DAW timestamp
1645+
uint64_t dawTimestamp = static_cast<uint64_t>(juce::Time::currentTimeMillis());
1646+
double playheadPosition = 0.0;
1647+
bool isPlaying = false;
1648+
1649+
// Get playhead info from DAW if available
1650+
if (auto* ph = getPlayHead())
1651+
{
1652+
juce::AudioPlayHead::CurrentPositionInfo currentPlayHeadInfo;
1653+
if (ph->getCurrentPosition(currentPlayHeadInfo))
1654+
{
1655+
isPlaying = currentPlayHeadInfo.isPlaying;
1656+
playheadPosition = currentPlayHeadInfo.timeInSeconds;
1657+
}
1658+
}
1659+
1660+
// Create parameter map with current panner settings
1661+
ParameterMap parameters;
1662+
parameters.addFloat(M1PannerParameterIDs::AZIMUTH, pannerSettings.azimuth.load());
1663+
parameters.addFloat(M1PannerParameterIDs::ELEVATION, pannerSettings.elevation.load());
1664+
parameters.addFloat(M1PannerParameterIDs::DIVERGE, pannerSettings.diverge.load());
1665+
parameters.addFloat(M1PannerParameterIDs::GAIN, pannerSettings.gain.load());
1666+
parameters.addFloat(M1PannerParameterIDs::STEREO_ORBIT_AZIMUTH, pannerSettings.stereoOrbitAzimuth.load());
1667+
parameters.addFloat(M1PannerParameterIDs::STEREO_SPREAD, pannerSettings.stereoSpread.load());
1668+
parameters.addFloat(M1PannerParameterIDs::STEREO_INPUT_BALANCE, pannerSettings.stereoInputBalance.load());
1669+
parameters.addBool(M1PannerParameterIDs::AUTO_ORBIT, pannerSettings.autoOrbit.load());
1670+
parameters.addBool(M1PannerParameterIDs::ISOTROPIC_MODE, pannerSettings.isotropicMode.load());
1671+
parameters.addBool(M1PannerParameterIDs::EQUALPOWER_MODE, pannerSettings.equalpowerMode.load());
1672+
parameters.addBool(M1PannerParameterIDs::GAIN_COMPENSATION_MODE, pannerSettings.gainCompensationMode.load());
1673+
parameters.addBool(M1PannerParameterIDs::LOCK_OUTPUT_LAYOUT, pannerSettings.lockOutputLayout.load());
1674+
1675+
// Add input/output mode info
1676+
{
1677+
std::lock_guard<std::mutex> lock(pannerSettings.processingMutex);
1678+
parameters.addInt(M1PannerParameterIDs::INPUT_MODE, static_cast<int32_t>(pannerSettings.m1Encode.getInputMode()));
1679+
parameters.addInt(M1PannerParameterIDs::OUTPUT_MODE, static_cast<int32_t>(pannerSettings.m1Encode.getOutputMode()));
1680+
}
1681+
1682+
// Add state, port, and color info
1683+
parameters.addInt(M1PannerParameterIDs::STATE, pannerSettings.state.load());
1684+
parameters.addInt(M1PannerParameterIDs::PORT, pannerSettings.port);
1685+
parameters.addInt(M1PannerParameterIDs::COLOR_R, static_cast<int32_t>(pannerSettings.color.r.load()));
1686+
parameters.addInt(M1PannerParameterIDs::COLOR_G, static_cast<int32_t>(pannerSettings.color.g.load()));
1687+
parameters.addInt(M1PannerParameterIDs::COLOR_B, static_cast<int32_t>(pannerSettings.color.b.load()));
1688+
parameters.addInt(M1PannerParameterIDs::COLOR_A, static_cast<int32_t>(pannerSettings.color.a.load()));
1689+
1690+
// Add display name (track name from host)
1691+
std::string displayName;
1692+
if (track_properties.name.has_value() && !track_properties.name->isEmpty())
1693+
{
1694+
displayName = track_properties.name->toStdString();
1695+
}
1696+
else
1697+
{
1698+
displayName = "M1-Panner (" + std::to_string(pannerSettings.port) + ")";
1699+
}
1700+
parameters.addString(M1PannerParameterIDs::DISPLAY_NAME, displayName);
1701+
1702+
// Create an empty audio buffer (0 samples) for parameter-only updates
1703+
juce::AudioBuffer<float> emptyBuffer(2, 0); // 2 channels, 0 samples
1704+
1705+
// Write parameters without audio data
1706+
m_memoryShare->writeAudioBufferWithGenericParameters(emptyBuffer, parameters, dawTimestamp, playheadPosition, isPlaying, false);
1707+
}
1708+
16021709
// ON-DEMAND SERVICE INTEGRATION: Helper method to check service availability
16031710
bool M1PannerAudioProcessor::isHelperServiceAvailable() const
16041711
{

Source/PluginProcessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class M1PannerAudioProcessor : public juce::AudioProcessor, juce::AudioProcessor
188188
juce::String m_instanceBaseName;
189189
void initializeMemorySharing();
190190
void updateMemorySharing(const juce::AudioBuffer<float>& inputBuffer);
191+
void updateMemorySharingParametersOnly(); // Update parameters even when audio isn't playing
191192

192193
/**
193194
* Apply external settings updates from memory share with priority handling

Source/TypesForDataExchange.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ struct GenericAudioBufferHeader
172172
uint32_t consumerCount; // Number of consumers that need to acknowledge
173173
uint32_t acknowledgedCount; // Number of consumers that have acknowledged
174174

175-
uint32_t reserved[1]; // Reserved for future expansion (reduced from 4 to 1)
175+
uint32_t reserved[2]; // Reserved for future expansion (reduced from 4 to 2)
176176

177177
// Parameters follow immediately after this struct
178178
// Each parameter is: GenericParameter + parameter data

0 commit comments

Comments
 (0)