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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pyhealth.processors.SenselabEGeMAPSProcessor
=============================================

.. autoclass:: pyhealth.processors.SenselabEGeMAPSProcessor
:members:
:undoc-members:
:show-inheritance:
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pyhealth.processors.SenselabEmbeddingProcessor
===============================================

.. autoclass:: pyhealth.processors.SenselabEmbeddingProcessor
:members:
:undoc-members:
:show-inheritance:
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pyhealth.processors.SenselabVADProcessor
=========================================

.. autoclass:: pyhealth.processors.SenselabVADProcessor
:members:
:undoc-members:
:show-inheritance:
70 changes: 70 additions & 0 deletions examples/senselab_processor_tutorial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
Senselab Processor Tutorial
============================
Demonstrates PyHealth's senselab processor wrappers for voice
biomarker extraction: VAD, eGeMAPS features, and speaker embeddings.

Use cases include depression detection, Parkinson's monitoring,
and cognitive assessment through voice.

Requires: pip install senselab
"""
import os
import tempfile

import torch
import torchaudio


def make_test_wav(path: str, sr: int = 16000, duration: float = 3.0) -> None:
"""Write a synthetic sine-wave audio file for demonstration."""
t = torch.linspace(0, duration, int(sr * duration))
waveform = torch.sin(2 * torch.pi * 440 * t).unsqueeze(0)
torchaudio.save(path, waveform, sr)


with tempfile.TemporaryDirectory() as tmpdir:
audio_path = os.path.join(tmpdir, "sample.wav")
make_test_wav(audio_path)

# ------------------------------------------------------------------
# 1. SenselabVADProcessor
# Strips silence and noise, returns speech-only waveform tensor.
# ------------------------------------------------------------------
from pyhealth.processors import SenselabVADProcessor

vad = SenselabVADProcessor(sample_rate=16000)
speech = vad.process(audio_path)
print(f"VAD output shape: {speech.shape}")
# Expected: torch.Size([1, N]) where N <= original samples

# ------------------------------------------------------------------
# 2. SenselabEGeMAPSProcessor
# Extracts 88 hand-crafted eGeMAPS acoustic features widely used
# in clinical voice research.
# ------------------------------------------------------------------
from pyhealth.processors import SenselabEGeMAPSProcessor

egemaps = SenselabEGeMAPSProcessor(sample_rate=16000, apply_vad=True)
features = egemaps.process(audio_path)
print(f"eGeMAPS output shape: {features.shape}")
# Expected: torch.Size([88])

# ------------------------------------------------------------------
# 3. SenselabEmbeddingProcessor
# Extracts deep neural speaker embeddings using WavLM or
# ECAPA-TDNN for voice biomarker tasks.
# ------------------------------------------------------------------
from pyhealth.processors import SenselabEmbeddingProcessor

# WavLM embedding (768-dim)
wavlm = SenselabEmbeddingProcessor(model="wavlm", sample_rate=16000)
embedding = wavlm.process(audio_path)
print(f"WavLM embedding shape: {embedding.shape}")
# Expected: torch.Size([768])

# ECAPA-TDNN embedding (192-dim)
ecapa = SenselabEmbeddingProcessor(model="ecapa", sample_rate=16000)
embedding_ecapa = ecapa.process(audio_path)
print(f"ECAPA embedding shape: {embedding_ecapa.shape}")
# Expected: torch.Size([192])
8 changes: 8 additions & 0 deletions pyhealth/processors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ def get_processor(name: str):


# Import all processors so they register themselves
from .senselab_processor import (
SenselabVADProcessor,
SenselabEGeMAPSProcessor,
SenselabEmbeddingProcessor,
)
from .image_processor import ImageProcessor
from .label_processor import (
BinaryLabelProcessor,
Expand Down Expand Up @@ -82,4 +87,7 @@ def get_processor(name: str):
"TupleTimeTextProcessor",
"CehrProcessor",
"ConceptVocab",
"SenselabVADProcessor",
"SenselabEGeMAPSProcessor",
"SenselabEmbeddingProcessor",
]
Loading