MicrophoneArrayProfile.java
package org.hammer.audio.acquisition;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
* Persistable hardware and geometry profile shared by simulation, replay and live localization.
*
* @param profileId stable profile identity
* @param displayName human-readable profile name
* @param layout geometry family used for presentation and validation
* @param array microphone geometry and channel mapping
* @param supportedModes localization input modes supported by the profile
* @param liveCapture capture configuration required for live mode, otherwise {@code null}
* @param calibration current calibration for this exact geometry and channel mapping, otherwise
* {@code null}
*/
public record MicrophoneArrayProfile(
String profileId,
String displayName,
MicrophoneArrayLayout layout,
MicrophoneArray array,
Set<LocalizationInputMode> supportedModes,
CaptureDeviceConfiguration liveCapture,
MicrophoneArrayCalibration calibration) {
// Validate one reusable profile and defensively copy its supported modes.
public MicrophoneArrayProfile {
requireText(profileId, "profileId");
requireText(displayName, "displayName");
Objects.requireNonNull(layout, "layout");
Objects.requireNonNull(array, "array");
Objects.requireNonNull(supportedModes, "supportedModes");
if (supportedModes.isEmpty()) {
throw new IllegalArgumentException("supportedModes must not be empty");
}
Set<LocalizationInputMode> modes = EnumSet.copyOf(supportedModes);
supportedModes = Collections.unmodifiableSet(modes);
if (modes.contains(LocalizationInputMode.LIVE) && liveCapture == null) {
throw new IllegalArgumentException("liveCapture is required when LIVE mode is supported");
}
if (liveCapture != null && liveCapture.format().channels() != array.channels()) {
throw new IllegalArgumentException(
"capture channel count must match microphone-array channel count");
}
if (calibration != null && !calibration.array().microphones().equals(array.microphones())) {
throw new IllegalArgumentException(
"calibration geometry and channel mapping must match the profile array");
}
}
/** Returns whether this profile can be used with one input mode. */
public boolean supports(LocalizationInputMode mode) {
return supportedModes.contains(Objects.requireNonNull(mode, "mode"));
}
/** Optional live capture configuration. */
public Optional<CaptureDeviceConfiguration> liveCaptureConfiguration() {
return Optional.ofNullable(liveCapture);
}
/** Optional timing and level calibration. */
public Optional<MicrophoneArrayCalibration> calibrationProfile() {
return Optional.ofNullable(calibration);
}
private static void requireText(String value, String name) {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException(name + " must not be blank");
}
}
}