@pipedog/core 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +25 -0
- package/NOTICE +9 -0
- package/dist/adapters/base_llm_adapter.d.ts +266 -0
- package/dist/adapters/base_llm_adapter.js +489 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +8 -0
- package/dist/adapters/schemas/direct_function.d.ts +202 -0
- package/dist/adapters/schemas/direct_function.js +302 -0
- package/dist/adapters/schemas/function_schema.d.ts +67 -0
- package/dist/adapters/schemas/function_schema.js +72 -0
- package/dist/adapters/schemas/index.d.ts +2 -0
- package/dist/adapters/schemas/index.js +8 -0
- package/dist/adapters/schemas/tools_schema.d.ts +57 -0
- package/dist/adapters/schemas/tools_schema.js +79 -0
- package/dist/adapters/services/index.d.ts +2 -0
- package/dist/adapters/services/index.js +8 -0
- package/dist/adapters/services/open_ai_adapter.d.ts +147 -0
- package/dist/adapters/services/open_ai_adapter.js +250 -0
- package/dist/audio/dtmf/dtmf_data.d.ts +3 -0
- package/dist/audio/dtmf/dtmf_data.js +22 -0
- package/dist/audio/dtmf/index.d.ts +2 -0
- package/dist/audio/dtmf/index.js +8 -0
- package/dist/audio/dtmf/types.d.ts +31 -0
- package/dist/audio/dtmf/types.js +35 -0
- package/dist/audio/dtmf/utils.d.ts +13 -0
- package/dist/audio/dtmf/utils.js +62 -0
- package/dist/audio/filters/base_audio_filter.d.ts +51 -0
- package/dist/audio/filters/base_audio_filter.js +17 -0
- package/dist/audio/filters/index.d.ts +2 -0
- package/dist/audio/filters/index.js +8 -0
- package/dist/audio/index.d.ts +2 -0
- package/dist/audio/index.js +8 -0
- package/dist/audio/krisp_instance.d.ts +95 -0
- package/dist/audio/krisp_instance.js +229 -0
- package/dist/audio/mixers/base_audio_mixer.d.ts +56 -0
- package/dist/audio/mixers/base_audio_mixer.js +16 -0
- package/dist/audio/mixers/index.d.ts +2 -0
- package/dist/audio/mixers/index.js +8 -0
- package/dist/audio/resamplers/base_audio_resampler.d.ts +46 -0
- package/dist/audio/resamplers/base_audio_resampler.js +35 -0
- package/dist/audio/resamplers/engine.d.ts +60 -0
- package/dist/audio/resamplers/engine.js +89 -0
- package/dist/audio/resamplers/index.d.ts +2 -0
- package/dist/audio/resamplers/index.js +8 -0
- package/dist/audio/resamplers/resampy_resampler.d.ts +10 -0
- package/dist/audio/resamplers/resampy_resampler.js +15 -0
- package/dist/audio/resamplers/sinc_engine.d.ts +10 -0
- package/dist/audio/resamplers/sinc_engine.js +235 -0
- package/dist/audio/resamplers/soxr_resampler.d.ts +58 -0
- package/dist/audio/resamplers/soxr_resampler.js +79 -0
- package/dist/audio/resamplers/soxr_stream_resampler.d.ts +78 -0
- package/dist/audio/resamplers/soxr_stream_resampler.js +159 -0
- package/dist/audio/turn/base_turn_analyzer.d.ts +84 -0
- package/dist/audio/turn/base_turn_analyzer.js +61 -0
- package/dist/audio/turn/index.d.ts +2 -0
- package/dist/audio/turn/index.js +8 -0
- package/dist/audio/turn/smart_turn/_whisper_features.d.ts +30 -0
- package/dist/audio/turn/smart_turn/_whisper_features.js +225 -0
- package/dist/audio/turn/smart_turn/base_smart_turn.d.ts +94 -0
- package/dist/audio/turn/smart_turn/base_smart_turn.js +239 -0
- package/dist/audio/turn/smart_turn/local_smart_turn_v3.d.ts +76 -0
- package/dist/audio/turn/smart_turn/local_smart_turn_v3.js +151 -0
- package/dist/audio/utils.d.ts +224 -0
- package/dist/audio/utils.js +634 -0
- package/dist/audio/vad/data/index.d.ts +2 -0
- package/dist/audio/vad/data/index.js +8 -0
- package/dist/audio/vad/index.d.ts +2 -0
- package/dist/audio/vad/index.js +8 -0
- package/dist/audio/vad/vad_analyzer.d.ts +134 -0
- package/dist/audio/vad/vad_analyzer.js +249 -0
- package/dist/audio/vad/vad_controller.d.ts +143 -0
- package/dist/audio/vad/vad_controller.js +228 -0
- package/dist/audio/volume.d.ts +38 -0
- package/dist/audio/volume.js +75 -0
- package/dist/bus/adapters/base.d.ts +35 -0
- package/dist/bus/adapters/base.js +19 -0
- package/dist/bus/adapters/index.d.ts +10 -0
- package/dist/bus/adapters/index.js +15 -0
- package/dist/bus/adapters/llm_context_adapter.d.ts +36 -0
- package/dist/bus/adapters/llm_context_adapter.js +82 -0
- package/dist/bus/adapters/tools_schema_adapter.d.ts +25 -0
- package/dist/bus/adapters/tools_schema_adapter.js +70 -0
- package/dist/bus/bridge_processor.d.ts +111 -0
- package/dist/bus/bridge_processor.js +166 -0
- package/dist/bus/bus.d.ts +110 -0
- package/dist/bus/bus.js +200 -0
- package/dist/bus/index.d.ts +22 -0
- package/dist/bus/index.js +27 -0
- package/dist/bus/local/async_queue.d.ts +12 -0
- package/dist/bus/local/async_queue.js +21 -0
- package/dist/bus/local/index.d.ts +3 -0
- package/dist/bus/local/index.js +8 -0
- package/dist/bus/messages.d.ts +378 -0
- package/dist/bus/messages.js +357 -0
- package/dist/bus/network/index.d.ts +16 -0
- package/dist/bus/network/index.js +21 -0
- package/dist/bus/queue.d.ts +27 -0
- package/dist/bus/queue.js +51 -0
- package/dist/bus/serializers/base.d.ts +25 -0
- package/dist/bus/serializers/base.js +14 -0
- package/dist/bus/serializers/index.d.ts +9 -0
- package/dist/bus/serializers/index.js +14 -0
- package/dist/bus/serializers/json.d.ts +77 -0
- package/dist/bus/serializers/json.js +367 -0
- package/dist/bus/subscriber.d.ts +46 -0
- package/dist/bus/subscriber.js +27 -0
- package/dist/bus/ui/index.d.ts +3 -0
- package/dist/bus/ui/index.js +8 -0
- package/dist/bus/ui/messages.d.ts +186 -0
- package/dist/bus/ui/messages.js +171 -0
- package/dist/classifiers/base_classifier.d.ts +263 -0
- package/dist/classifiers/base_classifier.js +346 -0
- package/dist/classifiers/cloudflare/clef/classifier.d.ts +70 -0
- package/dist/classifiers/cloudflare/clef/classifier.js +204 -0
- package/dist/classifiers/cloudflare/clef/client.d.ts +104 -0
- package/dist/classifiers/cloudflare/clef/client.js +234 -0
- package/dist/classifiers/cloudflare/clef/index.d.ts +2 -0
- package/dist/classifiers/cloudflare/clef/index.js +8 -0
- package/dist/classifiers/cloudflare/index.d.ts +2 -0
- package/dist/classifiers/cloudflare/index.js +8 -0
- package/dist/classifiers/http_client.d.ts +70 -0
- package/dist/classifiers/http_client.js +161 -0
- package/dist/classifiers/index.d.ts +2 -0
- package/dist/classifiers/index.js +8 -0
- package/dist/classifiers/jev/classifier.d.ts +8 -0
- package/dist/classifiers/jev/classifier.js +13 -0
- package/dist/classifiers/jev/client.d.ts +8 -0
- package/dist/classifiers/jev/client.js +13 -0
- package/dist/classifiers/jev/index.d.ts +2 -0
- package/dist/classifiers/jev/index.js +8 -0
- package/dist/classifiers/llm/classifier.d.ts +72 -0
- package/dist/classifiers/llm/classifier.js +304 -0
- package/dist/classifiers/llm/index.d.ts +2 -0
- package/dist/classifiers/llm/index.js +8 -0
- package/dist/classifiers/openai/decisions/classifier.d.ts +77 -0
- package/dist/classifiers/openai/decisions/classifier.js +241 -0
- package/dist/classifiers/openai/decisions/client.d.ts +108 -0
- package/dist/classifiers/openai/decisions/client.js +234 -0
- package/dist/classifiers/openai/decisions/index.d.ts +2 -0
- package/dist/classifiers/openai/decisions/index.js +8 -0
- package/dist/classifiers/openai/index.d.ts +2 -0
- package/dist/classifiers/openai/index.js +8 -0
- package/dist/classifiers/typesafe/index.d.ts +2 -0
- package/dist/classifiers/typesafe/index.js +8 -0
- package/dist/classifiers/typesafe/jev/classifier.d.ts +70 -0
- package/dist/classifiers/typesafe/jev/classifier.js +220 -0
- package/dist/classifiers/typesafe/jev/client.d.ts +105 -0
- package/dist/classifiers/typesafe/jev/client.js +233 -0
- package/dist/classifiers/typesafe/jev/index.d.ts +2 -0
- package/dist/classifiers/typesafe/jev/index.js +8 -0
- package/dist/clocks/base_clock.d.ts +13 -0
- package/dist/clocks/base_clock.js +14 -0
- package/dist/clocks/index.d.ts +2 -0
- package/dist/clocks/index.js +8 -0
- package/dist/clocks/system_clock.d.ts +15 -0
- package/dist/clocks/system_clock.js +25 -0
- package/dist/frames/frames.d.ts +2533 -0
- package/dist/frames/frames.js +2485 -0
- package/dist/frames/index.d.ts +2 -0
- package/dist/frames/index.js +8 -0
- package/dist/frames/protobufs/frames_pb2.d.ts +229 -0
- package/dist/frames/protobufs/frames_pb2.js +466 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +56 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.js +8 -0
- package/dist/metrics/metrics.d.ts +276 -0
- package/dist/metrics/metrics.js +254 -0
- package/dist/observers/base_observer.d.ts +173 -0
- package/dist/observers/base_observer.js +151 -0
- package/dist/observers/error_observer.d.ts +75 -0
- package/dist/observers/error_observer.js +87 -0
- package/dist/observers/function_call_observer.d.ts +157 -0
- package/dist/observers/function_call_observer.js +222 -0
- package/dist/observers/index.d.ts +2 -0
- package/dist/observers/index.js +8 -0
- package/dist/observers/loggers/debug_log_observer.d.ts +91 -0
- package/dist/observers/loggers/debug_log_observer.js +228 -0
- package/dist/observers/loggers/index.d.ts +2 -0
- package/dist/observers/loggers/index.js +8 -0
- package/dist/observers/loggers/llm_log_observer.d.ts +24 -0
- package/dist/observers/loggers/llm_log_observer.js +110 -0
- package/dist/observers/loggers/metrics_log_observer.d.ts +85 -0
- package/dist/observers/loggers/metrics_log_observer.js +186 -0
- package/dist/observers/loggers/transcription_log_observer.d.ts +23 -0
- package/dist/observers/loggers/transcription_log_observer.js +74 -0
- package/dist/observers/service_metrics_observer.d.ts +168 -0
- package/dist/observers/service_metrics_observer.js +236 -0
- package/dist/observers/speaking_observer.d.ts +104 -0
- package/dist/observers/speaking_observer.js +150 -0
- package/dist/observers/startup_timing_observer.d.ts +221 -0
- package/dist/observers/startup_timing_observer.js +365 -0
- package/dist/observers/turn_tracking_observer.d.ts +78 -0
- package/dist/observers/turn_tracking_observer.js +189 -0
- package/dist/observers/user_bot_latency_observer.d.ts +411 -0
- package/dist/observers/user_bot_latency_observer.js +974 -0
- package/dist/pipeline/base_pipeline.d.ts +49 -0
- package/dist/pipeline/base_pipeline.js +101 -0
- package/dist/pipeline/capabilities.d.ts +76 -0
- package/dist/pipeline/capabilities.js +97 -0
- package/dist/pipeline/index.d.ts +2 -0
- package/dist/pipeline/index.js +8 -0
- package/dist/pipeline/job_context.d.ts +317 -0
- package/dist/pipeline/job_context.js +450 -0
- package/dist/pipeline/job_decorator.d.ts +54 -0
- package/dist/pipeline/job_decorator.js +92 -0
- package/dist/pipeline/llm_switcher.d.ts +84 -0
- package/dist/pipeline/llm_switcher.js +107 -0
- package/dist/pipeline/llm_with_backend.d.ts +435 -0
- package/dist/pipeline/llm_with_backend.js +806 -0
- package/dist/pipeline/parallel_pipeline.d.ts +83 -0
- package/dist/pipeline/parallel_pipeline.js +200 -0
- package/dist/pipeline/pipeline.d.ts +126 -0
- package/dist/pipeline/pipeline.js +196 -0
- package/dist/pipeline/service_switcher.d.ts +287 -0
- package/dist/pipeline/service_switcher.js +509 -0
- package/dist/pipeline/sync_parallel_pipeline.d.ts +192 -0
- package/dist/pipeline/sync_parallel_pipeline.js +387 -0
- package/dist/pipeline/worker.d.ts +821 -0
- package/dist/pipeline/worker.js +1656 -0
- package/dist/pipeline/worker_observer.d.ts +131 -0
- package/dist/pipeline/worker_observer.js +274 -0
- package/dist/pipeline/worker_ready_decorator.d.ts +45 -0
- package/dist/pipeline/worker_ready_decorator.js +76 -0
- package/dist/processors/aggregators/async_tool_messages.d.ts +146 -0
- package/dist/processors/aggregators/async_tool_messages.js +291 -0
- package/dist/processors/aggregators/dtmf_aggregator.d.ts +61 -0
- package/dist/processors/aggregators/dtmf_aggregator.js +144 -0
- package/dist/processors/aggregators/gated.d.ts +43 -0
- package/dist/processors/aggregators/gated.js +86 -0
- package/dist/processors/aggregators/gated_llm_context.d.ts +42 -0
- package/dist/processors/aggregators/gated_llm_context.js +86 -0
- package/dist/processors/aggregators/index.d.ts +2 -0
- package/dist/processors/aggregators/index.js +8 -0
- package/dist/processors/aggregators/llm_context.d.ts +370 -0
- package/dist/processors/aggregators/llm_context.js +580 -0
- package/dist/processors/aggregators/llm_context_summarizer.d.ts +219 -0
- package/dist/processors/aggregators/llm_context_summarizer.js +447 -0
- package/dist/processors/aggregators/llm_response.d.ts +37 -0
- package/dist/processors/aggregators/llm_response.js +71 -0
- package/dist/processors/aggregators/llm_response_universal.d.ts +966 -0
- package/dist/processors/aggregators/llm_response_universal.js +2394 -0
- package/dist/processors/aggregators/llm_text_processor.d.ts +53 -0
- package/dist/processors/aggregators/llm_text_processor.js +102 -0
- package/dist/processors/aggregators/sentence.d.ts +39 -0
- package/dist/processors/aggregators/sentence.js +69 -0
- package/dist/processors/async_generator.d.ts +42 -0
- package/dist/processors/async_generator.js +76 -0
- package/dist/processors/audio/audio_buffer_processor.d.ts +241 -0
- package/dist/processors/audio/audio_buffer_processor.js +565 -0
- package/dist/processors/audio/index.d.ts +2 -0
- package/dist/processors/audio/index.js +8 -0
- package/dist/processors/audio/vad_processor.d.ts +67 -0
- package/dist/processors/audio/vad_processor.js +103 -0
- package/dist/processors/consumer_processor.d.ts +49 -0
- package/dist/processors/consumer_processor.js +85 -0
- package/dist/processors/filters/frame_filter.d.ts +39 -0
- package/dist/processors/filters/frame_filter.js +52 -0
- package/dist/processors/filters/function_filter.d.ts +59 -0
- package/dist/processors/filters/function_filter.js +78 -0
- package/dist/processors/filters/identity_filter.d.ts +33 -0
- package/dist/processors/filters/identity_filter.js +37 -0
- package/dist/processors/filters/index.d.ts +2 -0
- package/dist/processors/filters/index.js +8 -0
- package/dist/processors/filters/null_filter.d.ts +34 -0
- package/dist/processors/filters/null_filter.js +47 -0
- package/dist/processors/filters/wake_notifier_filter.d.ts +48 -0
- package/dist/processors/filters/wake_notifier_filter.js +49 -0
- package/dist/processors/frame_processor.d.ts +360 -0
- package/dist/processors/frame_processor.js +932 -0
- package/dist/processors/frameworks/index.d.ts +2 -0
- package/dist/processors/frameworks/index.js +8 -0
- package/dist/processors/frameworks/rtvi/frames.d.ts +241 -0
- package/dist/processors/frameworks/rtvi/frames.js +259 -0
- package/dist/processors/frameworks/rtvi/index.d.ts +6 -0
- package/dist/processors/frameworks/rtvi/index.js +11 -0
- package/dist/processors/frameworks/rtvi/models.d.ts +1741 -0
- package/dist/processors/frameworks/rtvi/models.js +1807 -0
- package/dist/processors/frameworks/rtvi/observer.d.ts +340 -0
- package/dist/processors/frameworks/rtvi/observer.js +1113 -0
- package/dist/processors/frameworks/rtvi/processor.d.ts +182 -0
- package/dist/processors/frameworks/rtvi/processor.js +676 -0
- package/dist/processors/idle_frame_processor.d.ts +44 -0
- package/dist/processors/idle_frame_processor.js +86 -0
- package/dist/processors/index.d.ts +2 -0
- package/dist/processors/index.js +8 -0
- package/dist/processors/logger.d.ts +42 -0
- package/dist/processors/logger.js +87 -0
- package/dist/processors/metrics/frame_processor_metrics.d.ts +172 -0
- package/dist/processors/metrics/frame_processor_metrics.js +372 -0
- package/dist/processors/metrics/index.d.ts +2 -0
- package/dist/processors/metrics/index.js +8 -0
- package/dist/processors/producer_processor.d.ts +68 -0
- package/dist/processors/producer_processor.js +78 -0
- package/dist/processors/text_transformer.d.ts +30 -0
- package/dist/processors/text_transformer.js +48 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/registry.d.ts +69 -0
- package/dist/registry/registry.js +149 -0
- package/dist/registry/types.d.ts +47 -0
- package/dist/registry/types.js +39 -0
- package/dist/serializers/base_serializer.d.ts +94 -0
- package/dist/serializers/base_serializer.js +82 -0
- package/dist/serializers/index.d.ts +2 -0
- package/dist/serializers/index.js +8 -0
- package/dist/services/ai_service.d.ts +145 -0
- package/dist/services/ai_service.js +262 -0
- package/dist/services/anthropic/index.d.ts +2 -0
- package/dist/services/anthropic/index.js +7 -0
- package/dist/services/assemblyai/index.d.ts +2 -0
- package/dist/services/assemblyai/index.js +7 -0
- package/dist/services/asyncai/index.d.ts +2 -0
- package/dist/services/asyncai/index.js +7 -0
- package/dist/services/aws/index.d.ts +2 -0
- package/dist/services/aws/index.js +7 -0
- package/dist/services/azure/index.d.ts +2 -0
- package/dist/services/azure/index.js +7 -0
- package/dist/services/baseten/index.d.ts +2 -0
- package/dist/services/baseten/index.js +7 -0
- package/dist/services/bland/index.d.ts +2 -0
- package/dist/services/bland/index.js +7 -0
- package/dist/services/camb/index.d.ts +2 -0
- package/dist/services/camb/index.js +7 -0
- package/dist/services/cartesia/index.d.ts +2 -0
- package/dist/services/cartesia/index.js +7 -0
- package/dist/services/cerebras/index.d.ts +2 -0
- package/dist/services/cerebras/index.js +7 -0
- package/dist/services/crusoe/index.d.ts +2 -0
- package/dist/services/crusoe/index.js +7 -0
- package/dist/services/deepgram/index.d.ts +2 -0
- package/dist/services/deepgram/index.js +7 -0
- package/dist/services/deepseek/index.d.ts +2 -0
- package/dist/services/deepseek/index.js +7 -0
- package/dist/services/elevenlabs/index.d.ts +2 -0
- package/dist/services/elevenlabs/index.js +7 -0
- package/dist/services/fal/index.d.ts +2 -0
- package/dist/services/fal/index.js +7 -0
- package/dist/services/fireworks/index.d.ts +2 -0
- package/dist/services/fireworks/index.js +7 -0
- package/dist/services/fish/index.d.ts +2 -0
- package/dist/services/fish/index.js +7 -0
- package/dist/services/funasr/index.d.ts +3 -0
- package/dist/services/funasr/index.js +8 -0
- package/dist/services/gladia/index.d.ts +2 -0
- package/dist/services/gladia/index.js +7 -0
- package/dist/services/google/index.d.ts +2 -0
- package/dist/services/google/index.js +7 -0
- package/dist/services/gradium/index.d.ts +2 -0
- package/dist/services/gradium/index.js +7 -0
- package/dist/services/grok/index.d.ts +2 -0
- package/dist/services/grok/index.js +7 -0
- package/dist/services/groq/index.d.ts +2 -0
- package/dist/services/groq/index.js +7 -0
- package/dist/services/heygen/index.d.ts +2 -0
- package/dist/services/heygen/index.js +7 -0
- package/dist/services/hume/index.d.ts +2 -0
- package/dist/services/hume/index.js +7 -0
- package/dist/services/image_service.d.ts +52 -0
- package/dist/services/image_service.js +60 -0
- package/dist/services/inception/index.d.ts +2 -0
- package/dist/services/inception/index.js +7 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +8 -0
- package/dist/services/inworld/index.d.ts +2 -0
- package/dist/services/inworld/index.js +7 -0
- package/dist/services/keenable/index.d.ts +2 -0
- package/dist/services/keenable/index.js +7 -0
- package/dist/services/kokoro/index.d.ts +2 -0
- package/dist/services/kokoro/index.js +7 -0
- package/dist/services/llm_service.d.ts +1106 -0
- package/dist/services/llm_service.js +2231 -0
- package/dist/services/mem0/index.d.ts +2 -0
- package/dist/services/mem0/index.js +7 -0
- package/dist/services/meta/index.d.ts +2 -0
- package/dist/services/meta/index.js +7 -0
- package/dist/services/minimax/index.d.ts +2 -0
- package/dist/services/minimax/index.js +7 -0
- package/dist/services/mistral/index.d.ts +2 -0
- package/dist/services/mistral/index.js +7 -0
- package/dist/services/moondream/index.d.ts +2 -0
- package/dist/services/moondream/index.js +7 -0
- package/dist/services/moonshine/index.d.ts +2 -0
- package/dist/services/moonshine/index.js +7 -0
- package/dist/services/nebius/index.d.ts +2 -0
- package/dist/services/nebius/index.js +7 -0
- package/dist/services/neuphonic/index.d.ts +2 -0
- package/dist/services/neuphonic/index.js +7 -0
- package/dist/services/novita/index.d.ts +2 -0
- package/dist/services/novita/index.js +7 -0
- package/dist/services/nvidia/index.d.ts +2 -0
- package/dist/services/nvidia/index.js +11 -0
- package/dist/services/ollama/index.d.ts +2 -0
- package/dist/services/ollama/index.js +7 -0
- package/dist/services/openai/index.d.ts +2 -0
- package/dist/services/openai/index.js +7 -0
- package/dist/services/openclaw/index.d.ts +14 -0
- package/dist/services/openclaw/index.js +19 -0
- package/dist/services/openrouter/index.d.ts +2 -0
- package/dist/services/openrouter/index.js +7 -0
- package/dist/services/perplexity/index.d.ts +2 -0
- package/dist/services/perplexity/index.js +7 -0
- package/dist/services/piper/index.d.ts +2 -0
- package/dist/services/piper/index.js +7 -0
- package/dist/services/pocket_tts/index.d.ts +2 -0
- package/dist/services/pocket_tts/index.js +7 -0
- package/dist/services/qwen/index.d.ts +2 -0
- package/dist/services/qwen/index.js +7 -0
- package/dist/services/resembleai/index.d.ts +2 -0
- package/dist/services/resembleai/index.js +7 -0
- package/dist/services/rime/index.d.ts +2 -0
- package/dist/services/rime/index.js +7 -0
- package/dist/services/sambanova/index.d.ts +2 -0
- package/dist/services/sambanova/index.js +7 -0
- package/dist/services/sarvam/index.d.ts +2 -0
- package/dist/services/sarvam/index.js +7 -0
- package/dist/services/settings.d.ts +356 -0
- package/dist/services/settings.js +437 -0
- package/dist/services/simli/index.d.ts +2 -0
- package/dist/services/simli/index.js +7 -0
- package/dist/services/smallest/index.d.ts +2 -0
- package/dist/services/smallest/index.js +7 -0
- package/dist/services/soniox/index.d.ts +2 -0
- package/dist/services/soniox/index.js +7 -0
- package/dist/services/speechify/index.d.ts +2 -0
- package/dist/services/speechify/index.js +7 -0
- package/dist/services/speechmatics/index.d.ts +2 -0
- package/dist/services/speechmatics/index.js +7 -0
- package/dist/services/stt_latency.d.ts +62 -0
- package/dist/services/stt_latency.js +71 -0
- package/dist/services/stt_service.d.ts +601 -0
- package/dist/services/stt_service.js +1044 -0
- package/dist/services/tavus/index.d.ts +2 -0
- package/dist/services/tavus/index.js +7 -0
- package/dist/services/together/index.d.ts +2 -0
- package/dist/services/together/index.js +7 -0
- package/dist/services/tts_service.d.ts +909 -0
- package/dist/services/tts_service.js +2018 -0
- package/dist/services/ultravox/index.d.ts +2 -0
- package/dist/services/ultravox/index.js +9 -0
- package/dist/services/vision_service.d.ts +56 -0
- package/dist/services/vision_service.js +62 -0
- package/dist/services/websocket_service.d.ts +213 -0
- package/dist/services/websocket_service.js +654 -0
- package/dist/services/whisper/index.d.ts +2 -0
- package/dist/services/whisper/index.js +9 -0
- package/dist/services/xai/index.d.ts +2 -0
- package/dist/services/xai/index.js +9 -0
- package/dist/services/xtts/index.d.ts +2 -0
- package/dist/services/xtts/index.js +9 -0
- package/dist/tests/index.d.ts +2 -0
- package/dist/tests/index.js +8 -0
- package/dist/tests/utils.d.ts +123 -0
- package/dist/tests/utils.js +212 -0
- package/dist/transcriptions/index.d.ts +2 -0
- package/dist/transcriptions/index.js +8 -0
- package/dist/transcriptions/language.d.ts +376 -0
- package/dist/transcriptions/language.js +543 -0
- package/dist/transports/base_input.d.ts +149 -0
- package/dist/transports/base_input.js +338 -0
- package/dist/transports/base_output.d.ts +432 -0
- package/dist/transports/base_output.js +1231 -0
- package/dist/transports/base_transport.d.ts +223 -0
- package/dist/transports/base_transport.js +167 -0
- package/dist/transports/daily/index.d.ts +2 -0
- package/dist/transports/daily/index.js +9 -0
- package/dist/transports/heygen/index.d.ts +2 -0
- package/dist/transports/heygen/index.js +9 -0
- package/dist/transports/index.d.ts +2 -0
- package/dist/transports/index.js +8 -0
- package/dist/transports/lemonslice/index.d.ts +2 -0
- package/dist/transports/lemonslice/index.js +9 -0
- package/dist/transports/livekit/index.d.ts +2 -0
- package/dist/transports/livekit/index.js +9 -0
- package/dist/transports/local/index.d.ts +2 -0
- package/dist/transports/local/index.js +9 -0
- package/dist/transports/moq/index.d.ts +2 -0
- package/dist/transports/moq/index.js +9 -0
- package/dist/transports/smallwebrtc/index.d.ts +2 -0
- package/dist/transports/smallwebrtc/index.js +9 -0
- package/dist/transports/tavus/index.d.ts +2 -0
- package/dist/transports/tavus/index.js +9 -0
- package/dist/transports/video_in_sampler.d.ts +157 -0
- package/dist/transports/video_in_sampler.js +258 -0
- package/dist/transports/vonage/index.d.ts +2 -0
- package/dist/transports/vonage/index.js +9 -0
- package/dist/transports/websocket/index.d.ts +2 -0
- package/dist/transports/websocket/index.js +9 -0
- package/dist/transports/whatsapp/index.d.ts +2 -0
- package/dist/transports/whatsapp/index.js +9 -0
- package/dist/turns/eager_end_of_turn_mixin.d.ts +70 -0
- package/dist/turns/eager_end_of_turn_mixin.js +122 -0
- package/dist/turns/empty_user_turn.d.ts +55 -0
- package/dist/turns/empty_user_turn.js +53 -0
- package/dist/turns/index.d.ts +2 -0
- package/dist/turns/index.js +8 -0
- package/dist/turns/speculation_gate.d.ts +169 -0
- package/dist/turns/speculation_gate.js +294 -0
- package/dist/turns/types.d.ts +33 -0
- package/dist/turns/types.js +35 -0
- package/dist/turns/user_idle_controller.d.ts +94 -0
- package/dist/turns/user_idle_controller.js +187 -0
- package/dist/turns/user_mute/always_user_mute_strategy.d.ts +15 -0
- package/dist/turns/user_mute/always_user_mute_strategy.js +29 -0
- package/dist/turns/user_mute/base_user_mute_strategy.d.ts +39 -0
- package/dist/turns/user_mute/base_user_mute_strategy.js +45 -0
- package/dist/turns/user_mute/first_speech_user_mute_strategy.d.ts +28 -0
- package/dist/turns/user_mute/first_speech_user_mute_strategy.js +52 -0
- package/dist/turns/user_mute/function_call_user_mute_strategy.d.ts +25 -0
- package/dist/turns/user_mute/function_call_user_mute_strategy.js +50 -0
- package/dist/turns/user_mute/index.d.ts +6 -0
- package/dist/turns/user_mute/index.js +11 -0
- package/dist/turns/user_mute/mute_until_first_bot_complete_user_mute_strategy.d.ts +43 -0
- package/dist/turns/user_mute/mute_until_first_bot_complete_user_mute_strategy.js +76 -0
- package/dist/turns/user_start/base_user_turn_start_strategy.d.ts +135 -0
- package/dist/turns/user_start/base_user_turn_start_strategy.js +134 -0
- package/dist/turns/user_start/external_user_turn_start_strategy.d.ts +45 -0
- package/dist/turns/user_start/external_user_turn_start_strategy.js +64 -0
- package/dist/turns/user_start/index.d.ts +8 -0
- package/dist/turns/user_start/index.js +16 -0
- package/dist/turns/user_start/krisp_viva_ip_user_turn_start_strategy.d.ts +133 -0
- package/dist/turns/user_start/krisp_viva_ip_user_turn_start_strategy.js +243 -0
- package/dist/turns/user_start/min_words_user_turn_start_strategy.d.ts +60 -0
- package/dist/turns/user_start/min_words_user_turn_start_strategy.js +102 -0
- package/dist/turns/user_start/transcription_user_turn_start_strategy.d.ts +29 -0
- package/dist/turns/user_start/transcription_user_turn_start_strategy.js +43 -0
- package/dist/turns/user_start/vad_user_turn_start_strategy.d.ts +20 -0
- package/dist/turns/user_start/vad_user_turn_start_strategy.js +31 -0
- package/dist/turns/user_start/wake_phrase_user_turn_start_strategy.d.ts +141 -0
- package/dist/turns/user_start/wake_phrase_user_turn_start_strategy.js +238 -0
- package/dist/turns/user_stop/base_user_turn_stop_strategy.d.ts +174 -0
- package/dist/turns/user_stop/base_user_turn_stop_strategy.js +170 -0
- package/dist/turns/user_stop/deferred_user_turn_stop_strategy.d.ts +81 -0
- package/dist/turns/user_stop/deferred_user_turn_stop_strategy.js +107 -0
- package/dist/turns/user_stop/eager_match_policy.d.ts +36 -0
- package/dist/turns/user_stop/eager_match_policy.js +50 -0
- package/dist/turns/user_stop/eager_user_turn_stop_strategy.d.ts +84 -0
- package/dist/turns/user_stop/eager_user_turn_stop_strategy.js +154 -0
- package/dist/turns/user_stop/external_user_turn_completion_stop_strategy.d.ts +45 -0
- package/dist/turns/user_stop/external_user_turn_completion_stop_strategy.js +55 -0
- package/dist/turns/user_stop/external_user_turn_stop_strategy.d.ts +115 -0
- package/dist/turns/user_stop/external_user_turn_stop_strategy.js +205 -0
- package/dist/turns/user_stop/index.d.ts +10 -0
- package/dist/turns/user_stop/index.js +15 -0
- package/dist/turns/user_stop/llm_turn_completion_user_turn_stop_strategy.d.ts +44 -0
- package/dist/turns/user_stop/llm_turn_completion_user_turn_stop_strategy.js +59 -0
- package/dist/turns/user_stop/speech_timeout_user_turn_stop_strategy.d.ts +140 -0
- package/dist/turns/user_stop/speech_timeout_user_turn_stop_strategy.js +303 -0
- package/dist/turns/user_stop/turn_analyzer_user_turn_stop_strategy.d.ts +135 -0
- package/dist/turns/user_stop/turn_analyzer_user_turn_stop_strategy.js +332 -0
- package/dist/turns/user_turn_completion_mixin.d.ts +147 -0
- package/dist/turns/user_turn_completion_mixin.js +591 -0
- package/dist/turns/user_turn_controller.d.ts +134 -0
- package/dist/turns/user_turn_controller.js +335 -0
- package/dist/turns/user_turn_processor.d.ts +87 -0
- package/dist/turns/user_turn_processor.js +180 -0
- package/dist/turns/user_turn_strategies.d.ts +187 -0
- package/dist/turns/user_turn_strategies.js +222 -0
- package/dist/utils/async_tool_cancellation.d.ts +35 -0
- package/dist/utils/async_tool_cancellation.js +78 -0
- package/dist/utils/asyncio/index.d.ts +2 -0
- package/dist/utils/asyncio/index.js +7 -0
- package/dist/utils/asyncio/task_manager.d.ts +49 -0
- package/dist/utils/asyncio/task_manager.js +105 -0
- package/dist/utils/base_object.d.ts +76 -0
- package/dist/utils/base_object.js +154 -0
- package/dist/utils/context/aggregated_frame_sequencer.d.ts +491 -0
- package/dist/utils/context/aggregated_frame_sequencer.js +803 -0
- package/dist/utils/context/audio_context_manager.d.ts +131 -0
- package/dist/utils/context/audio_context_manager.js +233 -0
- package/dist/utils/context/index.d.ts +2 -0
- package/dist/utils/context/index.js +7 -0
- package/dist/utils/context/llm_context_summarization.d.ts +258 -0
- package/dist/utils/context/llm_context_summarization.js +511 -0
- package/dist/utils/context/text_segment_map.d.ts +611 -0
- package/dist/utils/context/text_segment_map.js +1132 -0
- package/dist/utils/context/word_completion_tracker.d.ts +273 -0
- package/dist/utils/context/word_completion_tracker.js +441 -0
- package/dist/utils/context/word_timestamp_tracker.d.ts +72 -0
- package/dist/utils/context/word_timestamp_tracker.js +98 -0
- package/dist/utils/deprecation.d.ts +28 -0
- package/dist/utils/deprecation.js +75 -0
- package/dist/utils/env.d.ts +38 -0
- package/dist/utils/env.js +62 -0
- package/dist/utils/errors.d.ts +75 -0
- package/dist/utils/errors.js +202 -0
- package/dist/utils/file_resolver.d.ts +126 -0
- package/dist/utils/file_resolver.js +314 -0
- package/dist/utils/file_storage.d.ts +115 -0
- package/dist/utils/file_storage.js +178 -0
- package/dist/utils/frame_queue.d.ts +36 -0
- package/dist/utils/frame_queue.js +66 -0
- package/dist/utils/http.d.ts +39 -0
- package/dist/utils/http.js +53 -0
- package/dist/utils/image.d.ts +14 -0
- package/dist/utils/image.js +63 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jpeg_encoder.d.ts +14 -0
- package/dist/utils/jpeg_encoder.js +315 -0
- package/dist/utils/log_config.d.ts +34 -0
- package/dist/utils/log_config.js +76 -0
- package/dist/utils/logger.d.ts +40 -0
- package/dist/utils/logger.js +91 -0
- package/dist/utils/mixin.d.ts +14 -0
- package/dist/utils/mixin.js +63 -0
- package/dist/utils/network.d.ts +73 -0
- package/dist/utils/network.js +90 -0
- package/dist/utils/security/allowed_origins.d.ts +16 -0
- package/dist/utils/security/allowed_origins.js +34 -0
- package/dist/utils/security/index.d.ts +2 -0
- package/dist/utils/security/index.js +7 -0
- package/dist/utils/security/redaction.d.ts +27 -0
- package/dist/utils/security/redaction.js +123 -0
- package/dist/utils/security/ssrf.d.ts +79 -0
- package/dist/utils/security/ssrf.js +327 -0
- package/dist/utils/shared.d.ts +35 -0
- package/dist/utils/shared.js +136 -0
- package/dist/utils/startup.d.ts +17 -0
- package/dist/utils/startup.js +130 -0
- package/dist/utils/string.d.ts +116 -0
- package/dist/utils/string.js +460 -0
- package/dist/utils/sync/base_notifier.d.ts +25 -0
- package/dist/utils/sync/base_notifier.js +16 -0
- package/dist/utils/sync/event_notifier.d.ts +38 -0
- package/dist/utils/sync/event_notifier.js +51 -0
- package/dist/utils/sync/index.d.ts +2 -0
- package/dist/utils/sync/index.js +7 -0
- package/dist/utils/text/alnum_utils.d.ts +109 -0
- package/dist/utils/text/alnum_utils.js +262 -0
- package/dist/utils/text/base_text_aggregator.d.ts +146 -0
- package/dist/utils/text/base_text_aggregator.js +102 -0
- package/dist/utils/text/base_text_filter.d.ts +54 -0
- package/dist/utils/text/base_text_filter.js +50 -0
- package/dist/utils/text/index.d.ts +2 -0
- package/dist/utils/text/index.js +7 -0
- package/dist/utils/text/markdown_text_filter.d.ts +147 -0
- package/dist/utils/text/markdown_text_filter.js +522 -0
- package/dist/utils/text/markup_utils.d.ts +54 -0
- package/dist/utils/text/markup_utils.js +156 -0
- package/dist/utils/text/pattern_pair_aggregator.d.ts +251 -0
- package/dist/utils/text/pattern_pair_aggregator.js +478 -0
- package/dist/utils/text/phonemes.d.ts +60 -0
- package/dist/utils/text/phonemes.js +172 -0
- package/dist/utils/text/simple_text_aggregator.d.ts +135 -0
- package/dist/utils/text/simple_text_aggregator.js +254 -0
- package/dist/utils/text/skip_tags_aggregator.d.ts +85 -0
- package/dist/utils/text/skip_tags_aggregator.js +147 -0
- package/dist/utils/text/transforms/acronyms.d.ts +21 -0
- package/dist/utils/text/transforms/acronyms.js +31 -0
- package/dist/utils/text/transforms/currency.d.ts +16 -0
- package/dist/utils/text/transforms/currency.js +56 -0
- package/dist/utils/text/transforms/dates.d.ts +18 -0
- package/dist/utils/text/transforms/dates.js +102 -0
- package/dist/utils/text/transforms/email.d.ts +17 -0
- package/dist/utils/text/transforms/email.js +35 -0
- package/dist/utils/text/transforms/index.d.ts +37 -0
- package/dist/utils/text/transforms/index.js +42 -0
- package/dist/utils/text/transforms/numbers.d.ts +25 -0
- package/dist/utils/text/transforms/numbers.js +59 -0
- package/dist/utils/text/transforms/percentages.d.ts +16 -0
- package/dist/utils/text/transforms/percentages.js +32 -0
- package/dist/utils/text/transforms/phone.d.ts +21 -0
- package/dist/utils/text/transforms/phone.js +39 -0
- package/dist/utils/text/transforms/pronunciations.d.ts +65 -0
- package/dist/utils/text/transforms/pronunciations.js +112 -0
- package/dist/utils/text/transforms/replacements.d.ts +39 -0
- package/dist/utils/text/transforms/replacements.js +46 -0
- package/dist/utils/text/transforms/strip_markdown.d.ts +25 -0
- package/dist/utils/text/transforms/strip_markdown.js +60 -0
- package/dist/utils/text/transforms/units.d.ts +22 -0
- package/dist/utils/text/transforms/units.js +81 -0
- package/dist/utils/text/transforms/voice_formatter.d.ts +86 -0
- package/dist/utils/text/transforms/voice_formatter.js +98 -0
- package/dist/utils/text/unicode_digits.d.ts +3 -0
- package/dist/utils/text/unicode_digits.js +34 -0
- package/dist/utils/text/word_timestamp_utils.d.ts +26 -0
- package/dist/utils/text/word_timestamp_utils.js +52 -0
- package/dist/utils/time.d.ts +13 -0
- package/dist/utils/time.js +31 -0
- package/dist/utils/tracing/index.d.ts +3 -0
- package/dist/utils/tracing/index.js +8 -0
- package/dist/utils/tracing/service_attributes.d.ts +198 -0
- package/dist/utils/tracing/service_attributes.js +434 -0
- package/dist/utils/tracing/service_decorators.d.ts +214 -0
- package/dist/utils/tracing/service_decorators.js +1662 -0
- package/dist/utils/tracing/setup.d.ts +107 -0
- package/dist/utils/tracing/setup.js +160 -0
- package/dist/utils/tracing/tracing_context.d.ts +55 -0
- package/dist/utils/tracing/tracing_context.js +97 -0
- package/dist/utils/tracing/turn_trace_observer.d.ts +95 -0
- package/dist/utils/tracing/turn_trace_observer.js +233 -0
- package/dist/utils/types.d.ts +80 -0
- package/dist/utils/types.js +108 -0
- package/dist/utils/utils.d.ts +5 -0
- package/dist/utils/utils.js +22 -0
- package/dist/utils/yaml.d.ts +179 -0
- package/dist/utils/yaml.js +556 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +7 -0
- package/dist/workers/base_worker.d.ts +772 -0
- package/dist/workers/base_worker.js +1298 -0
- package/dist/workers/index.d.ts +2 -0
- package/dist/workers/index.js +8 -0
- package/dist/workers/llm/backend_llm_worker.d.ts +552 -0
- package/dist/workers/llm/backend_llm_worker.js +1055 -0
- package/dist/workers/llm/index.d.ts +6 -0
- package/dist/workers/llm/index.js +11 -0
- package/dist/workers/llm/llm_context_worker.d.ts +66 -0
- package/dist/workers/llm/llm_context_worker.js +72 -0
- package/dist/workers/llm/llm_worker.d.ts +180 -0
- package/dist/workers/llm/llm_worker.js +323 -0
- package/dist/workers/llm/tool_decorator.d.ts +68 -0
- package/dist/workers/llm/tool_decorator.js +60 -0
- package/dist/workers/proxy/index.d.ts +3 -0
- package/dist/workers/proxy/index.js +9 -0
- package/dist/workers/proxy/websocket/client.d.ts +110 -0
- package/dist/workers/proxy/websocket/client.js +196 -0
- package/dist/workers/proxy/websocket/index.d.ts +3 -0
- package/dist/workers/proxy/websocket/index.js +10 -0
- package/dist/workers/runner.d.ts +268 -0
- package/dist/workers/runner.js +489 -0
- package/dist/workers/ui/index.d.ts +22 -0
- package/dist/workers/ui/index.js +27 -0
- package/dist/workers/ui/ui_event_decorator.d.ts +43 -0
- package/dist/workers/ui/ui_event_decorator.js +75 -0
- package/dist/workers/ui/ui_job_context.d.ts +12 -0
- package/dist/workers/ui/ui_job_context.js +17 -0
- package/dist/workers/ui/ui_prompts.d.ts +21 -0
- package/dist/workers/ui/ui_prompts.js +41 -0
- package/dist/workers/ui/ui_tools.d.ts +32 -0
- package/dist/workers/ui/ui_tools.js +112 -0
- package/dist/workers/ui/ui_worker.d.ts +571 -0
- package/dist/workers/ui/ui_worker.js +1156 -0
- package/package.json +61 -3
- package/README.md +0 -5
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026, Daily
|
|
2
|
+
// Copyright (c) 2026, pipedog contributors
|
|
3
|
+
// SPDX-License-Identifier: BSD-2-Clause
|
|
4
|
+
//
|
|
5
|
+
// Ported from pipecat: src/pipecat/audio/utils.py
|
|
6
|
+
import { bytesToInt16, SOXRAudioResampler, } from "./resamplers/soxr_resampler.js";
|
|
7
|
+
import { SOXRStreamAudioResampler, } from "./resamplers/soxr_stream_resampler.js";
|
|
8
|
+
// Normal speech usually results in many samples between ±500 to ±5000,
|
|
9
|
+
// depending on loudness and mic gain. So we are using a threshold that is well
|
|
10
|
+
// below what real speech produces.
|
|
11
|
+
export const SPEAKING_THRESHOLD = 20;
|
|
12
|
+
function int16ToBytes(samples) {
|
|
13
|
+
return new Uint8Array(samples.buffer, samples.byteOffset, samples.byteLength);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create an audio resampler instance for batch processing of complete audio
|
|
17
|
+
* files.
|
|
18
|
+
*
|
|
19
|
+
* @param options Options passed to the resampler constructor.
|
|
20
|
+
* @returns A configured SOXRAudioResampler instance.
|
|
21
|
+
*/
|
|
22
|
+
export function createFileResampler(options = {}) {
|
|
23
|
+
return new SOXRAudioResampler(options);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a stream audio resampler instance.
|
|
27
|
+
*
|
|
28
|
+
* @param options Options passed to the resampler constructor.
|
|
29
|
+
* @returns A configured SOXRStreamAudioResampler instance.
|
|
30
|
+
*/
|
|
31
|
+
export function createStreamResampler(options = {}) {
|
|
32
|
+
return new SOXRStreamAudioResampler(options);
|
|
33
|
+
}
|
|
34
|
+
function clipInt16(value) {
|
|
35
|
+
return value < -32768 ? -32768 : value > 32767 ? 32767 : value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Mix two audio streams together by adding their samples.
|
|
39
|
+
*
|
|
40
|
+
* Both audio streams are assumed to be 16-bit signed integer PCM data. If the
|
|
41
|
+
* streams have different lengths, the shorter one is zero-padded to match the
|
|
42
|
+
* longer stream.
|
|
43
|
+
*
|
|
44
|
+
* @param audio1 First audio stream as raw bytes (16-bit signed integers).
|
|
45
|
+
* @param audio2 Second audio stream as raw bytes (16-bit signed integers).
|
|
46
|
+
* @returns Mixed audio data as raw bytes with samples clipped to 16-bit range.
|
|
47
|
+
*/
|
|
48
|
+
export function mixAudio(audio1, audio2) {
|
|
49
|
+
const data1 = bytesToInt16(audio1);
|
|
50
|
+
const data2 = bytesToInt16(audio2);
|
|
51
|
+
// Max length
|
|
52
|
+
const maxLength = Math.max(data1.length, data2.length);
|
|
53
|
+
// Mix the arrays (zero-padding the shorter one)
|
|
54
|
+
const mixedAudio = new Int16Array(maxLength);
|
|
55
|
+
for (let i = 0; i < maxLength; i++) {
|
|
56
|
+
const a = i < data1.length ? data1[i] : 0;
|
|
57
|
+
const b = i < data2.length ? data2[i] : 0;
|
|
58
|
+
mixedAudio[i] = clipInt16(a + b);
|
|
59
|
+
}
|
|
60
|
+
return int16ToBytes(mixedAudio);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Scale the volume of an audio stream by multiplying its samples.
|
|
64
|
+
*
|
|
65
|
+
* The audio is assumed to be 16-bit signed integer PCM data.
|
|
66
|
+
*
|
|
67
|
+
* @param audio Audio as raw bytes (16-bit signed integers).
|
|
68
|
+
* @param factor The multiplier for every sample: 1.0 leaves the audio
|
|
69
|
+
* unchanged, 0.5 halves it.
|
|
70
|
+
* @returns Scaled audio data as raw bytes with samples clipped to 16-bit range.
|
|
71
|
+
*/
|
|
72
|
+
export function scaleAudio(audio, factor) {
|
|
73
|
+
const data = bytesToInt16(audio);
|
|
74
|
+
const out = new Int16Array(data.length);
|
|
75
|
+
const f = Math.fround(factor);
|
|
76
|
+
for (let i = 0; i < data.length; i++) {
|
|
77
|
+
// numpy computes in float32, clips, then truncates toward zero.
|
|
78
|
+
out[i] = Math.trunc(clipInt16(Math.fround(data[i] * f)));
|
|
79
|
+
}
|
|
80
|
+
return int16ToBytes(out);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Interleave left and right mono audio channels into stereo audio.
|
|
84
|
+
*
|
|
85
|
+
* Takes two mono audio streams and combines them into a single stereo stream
|
|
86
|
+
* by interleaving the samples (L, R, L, R, ...). If the channels have
|
|
87
|
+
* different lengths, both are truncated to the shorter length.
|
|
88
|
+
*
|
|
89
|
+
* @param leftAudio Left channel audio as raw bytes (16-bit signed integers).
|
|
90
|
+
* @param rightAudio Right channel audio as raw bytes (16-bit signed integers).
|
|
91
|
+
* @returns Interleaved stereo audio data as raw bytes.
|
|
92
|
+
*/
|
|
93
|
+
export function interleaveStereoAudio(leftAudio, rightAudio) {
|
|
94
|
+
const left = bytesToInt16(leftAudio);
|
|
95
|
+
const right = bytesToInt16(rightAudio);
|
|
96
|
+
const minLength = Math.min(left.length, right.length);
|
|
97
|
+
const stereo = new Int16Array(minLength * 2);
|
|
98
|
+
for (let i = 0; i < minLength; i++) {
|
|
99
|
+
stereo[2 * i] = left[i];
|
|
100
|
+
stereo[2 * i + 1] = right[i];
|
|
101
|
+
}
|
|
102
|
+
return int16ToBytes(stereo);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Wrap raw PCM audio in a WAV container.
|
|
106
|
+
*
|
|
107
|
+
* The PCM data is expected to be signed 16-bit little-endian samples, which
|
|
108
|
+
* is what Pipecat pipelines carry (e.g. what `AudioBufferProcessor` emits
|
|
109
|
+
* from its audio event handlers).
|
|
110
|
+
*
|
|
111
|
+
* Trailing bytes that don't complete a frame are dropped. Without this the
|
|
112
|
+
* WAV header would report a frame count that excludes them while the data
|
|
113
|
+
* chunk still carries them, so readers would disagree about the length and a
|
|
114
|
+
* stereo stream truncated mid-frame would swap channels.
|
|
115
|
+
*
|
|
116
|
+
* @param pcm Raw PCM audio data (16-bit signed integers). Any typed view
|
|
117
|
+
* (e.g. an `Int16Array`) is read as its underlying bytes.
|
|
118
|
+
* @param sampleRate Sample rate of the audio in Hz.
|
|
119
|
+
* @param numChannels Number of interleaved channels in the PCM data.
|
|
120
|
+
* @returns A complete in-memory WAV file.
|
|
121
|
+
*/
|
|
122
|
+
export function pcmToWav(input, sampleRate, numChannels = 1) {
|
|
123
|
+
// Upstream: `memoryview(pcm).cast("B")`.
|
|
124
|
+
let pcm = input instanceof Uint8Array
|
|
125
|
+
? input
|
|
126
|
+
: new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
127
|
+
const blockAlign = 2 * numChannels;
|
|
128
|
+
const remainder = pcm.length % blockAlign;
|
|
129
|
+
if (remainder) {
|
|
130
|
+
pcm = pcm.subarray(0, pcm.length - remainder);
|
|
131
|
+
}
|
|
132
|
+
// Same layout Python's `wave` module writes: RIFF header, 16-byte PCM fmt
|
|
133
|
+
// chunk, data chunk (padded to an even length).
|
|
134
|
+
const dataLength = pcm.length;
|
|
135
|
+
const pad = dataLength % 2;
|
|
136
|
+
const out = new Uint8Array(44 + dataLength + pad);
|
|
137
|
+
const view = new DataView(out.buffer);
|
|
138
|
+
const ascii = (offset, s) => {
|
|
139
|
+
for (let i = 0; i < s.length; i++)
|
|
140
|
+
out[offset + i] = s.charCodeAt(i);
|
|
141
|
+
};
|
|
142
|
+
ascii(0, "RIFF");
|
|
143
|
+
view.setUint32(4, 36 + dataLength + pad, true);
|
|
144
|
+
ascii(8, "WAVE");
|
|
145
|
+
ascii(12, "fmt ");
|
|
146
|
+
view.setUint32(16, 16, true);
|
|
147
|
+
view.setUint16(20, 1, true); // WAVE_FORMAT_PCM
|
|
148
|
+
view.setUint16(22, numChannels, true);
|
|
149
|
+
view.setUint32(24, sampleRate, true);
|
|
150
|
+
view.setUint32(28, sampleRate * blockAlign, true);
|
|
151
|
+
view.setUint16(32, blockAlign, true);
|
|
152
|
+
view.setUint16(34, 16, true);
|
|
153
|
+
ascii(36, "data");
|
|
154
|
+
view.setUint32(40, dataLength, true);
|
|
155
|
+
out.set(pcm, 44);
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Read the PCM frames out of a WAV file (Python's `wave.open(...).readframes()`).
|
|
160
|
+
*
|
|
161
|
+
* @internal
|
|
162
|
+
*/
|
|
163
|
+
export function readWav(data) {
|
|
164
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
165
|
+
const tag = (offset) => String.fromCharCode(...data.subarray(offset, offset + 4));
|
|
166
|
+
if (tag(0) !== "RIFF" || tag(8) !== "WAVE") {
|
|
167
|
+
throw new Error("file does not start with RIFF id");
|
|
168
|
+
}
|
|
169
|
+
let offset = 12;
|
|
170
|
+
let sampleRate = 0;
|
|
171
|
+
let numChannels = 0;
|
|
172
|
+
let sampleWidth = 0;
|
|
173
|
+
let audio = null;
|
|
174
|
+
while (offset + 8 <= data.length) {
|
|
175
|
+
const id = tag(offset);
|
|
176
|
+
const size = view.getUint32(offset + 4, true);
|
|
177
|
+
const body = offset + 8;
|
|
178
|
+
if (id === "fmt ") {
|
|
179
|
+
numChannels = view.getUint16(body + 2, true);
|
|
180
|
+
sampleRate = view.getUint32(body + 4, true);
|
|
181
|
+
sampleWidth = Math.ceil(view.getUint16(body + 14, true) / 8);
|
|
182
|
+
}
|
|
183
|
+
else if (id === "data") {
|
|
184
|
+
audio = data.slice(body, Math.min(body + size, data.length));
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
offset = body + size + (size % 2);
|
|
188
|
+
}
|
|
189
|
+
if (!audio || !sampleRate) {
|
|
190
|
+
throw new Error("fmt chunk and/or data chunk missing");
|
|
191
|
+
}
|
|
192
|
+
return { audio, sampleRate, numChannels, sampleWidth };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Normalize a value to the range [0, 1] and clamp it to bounds.
|
|
196
|
+
*
|
|
197
|
+
* @param value The value to normalize.
|
|
198
|
+
* @param minValue The minimum value of the input range.
|
|
199
|
+
* @param maxValue The maximum value of the input range.
|
|
200
|
+
* @returns Normalized value clamped to the range [0, 1].
|
|
201
|
+
*/
|
|
202
|
+
export function normalizeValue(value, minValue, maxValue) {
|
|
203
|
+
const normalized = (value - minValue) / (maxValue - minValue);
|
|
204
|
+
const normalizedClamped = Math.max(0, Math.min(1, normalized));
|
|
205
|
+
return normalizedClamped;
|
|
206
|
+
}
|
|
207
|
+
// K-weighting filter design for an arbitrary sample rate (the same analog
|
|
208
|
+
// prototype parameters used by libebur128 and pyloudnorm).
|
|
209
|
+
function kWeightingFilters(rate) {
|
|
210
|
+
// Stage 1: high shelf.
|
|
211
|
+
let f0 = 1681.974450955533;
|
|
212
|
+
const G = 3.999843853973347;
|
|
213
|
+
let Q = 0.7071752369554196;
|
|
214
|
+
let K = Math.tan((Math.PI * f0) / rate);
|
|
215
|
+
const Vh = 10 ** (G / 20);
|
|
216
|
+
const Vb = Vh ** 0.4996667741545416;
|
|
217
|
+
let a0 = 1 + K / Q + K * K;
|
|
218
|
+
const shelf = {
|
|
219
|
+
b: [
|
|
220
|
+
(Vh + (Vb * K) / Q + K * K) / a0,
|
|
221
|
+
(2 * (K * K - Vh)) / a0,
|
|
222
|
+
(Vh - (Vb * K) / Q + K * K) / a0,
|
|
223
|
+
],
|
|
224
|
+
a: [1, (2 * (K * K - 1)) / a0, (1 - K / Q + K * K) / a0],
|
|
225
|
+
};
|
|
226
|
+
// Stage 2: high pass (RLB).
|
|
227
|
+
f0 = 38.13547087602444;
|
|
228
|
+
Q = 0.5003270373238773;
|
|
229
|
+
K = Math.tan((Math.PI * f0) / rate);
|
|
230
|
+
a0 = 1 + K / Q + K * K;
|
|
231
|
+
const highPass = {
|
|
232
|
+
b: [1, -2, 1],
|
|
233
|
+
a: [1, (2 * (K * K - 1)) / a0, (1 - K / Q + K * K) / a0],
|
|
234
|
+
};
|
|
235
|
+
return [shelf, highPass];
|
|
236
|
+
}
|
|
237
|
+
function applyBiquad(input, { b, a }) {
|
|
238
|
+
const out = new Float64Array(input.length);
|
|
239
|
+
let x1 = 0;
|
|
240
|
+
let x2 = 0;
|
|
241
|
+
let y1 = 0;
|
|
242
|
+
let y2 = 0;
|
|
243
|
+
for (let i = 0; i < input.length; i++) {
|
|
244
|
+
const x = input[i];
|
|
245
|
+
const y = b[0] * x + b[1] * x1 + b[2] * x2 - a[1] * y1 - a[2] * y2;
|
|
246
|
+
x2 = x1;
|
|
247
|
+
x1 = x;
|
|
248
|
+
y2 = y1;
|
|
249
|
+
y1 = y;
|
|
250
|
+
out[i] = y;
|
|
251
|
+
}
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
function integratedLoudness(samples, rate) {
|
|
255
|
+
const blockSize = 0.4;
|
|
256
|
+
const blockLength = Math.round(blockSize * rate);
|
|
257
|
+
if (samples.length < blockLength) {
|
|
258
|
+
throw new Error("Audio must have length greater than the block size.");
|
|
259
|
+
}
|
|
260
|
+
const [shelf, highPass] = kWeightingFilters(rate);
|
|
261
|
+
const filtered = applyBiquad(applyBiquad(samples, shelf), highPass);
|
|
262
|
+
// 400 ms gating blocks with 75% overlap.
|
|
263
|
+
const step = blockSize * 0.25;
|
|
264
|
+
const numBlocks = Math.round((samples.length / rate - blockSize) / step) + 1;
|
|
265
|
+
const z = [];
|
|
266
|
+
for (let j = 0; j < numBlocks; j++) {
|
|
267
|
+
const lower = Math.trunc(blockSize * (j * 0.25) * rate);
|
|
268
|
+
const upper = Math.min(Math.trunc(blockSize * (j * 0.25 + 1) * rate), filtered.length);
|
|
269
|
+
let sum = 0;
|
|
270
|
+
for (let i = lower; i < upper; i++) {
|
|
271
|
+
const v = filtered[i];
|
|
272
|
+
sum += v * v;
|
|
273
|
+
}
|
|
274
|
+
z.push(sum / (blockSize * rate));
|
|
275
|
+
}
|
|
276
|
+
const blockLoudness = (zj) => -0.691 + 10 * Math.log10(zj);
|
|
277
|
+
// Absolute gate.
|
|
278
|
+
const gammaA = -70.0;
|
|
279
|
+
const aboveAbs = z.filter((zj) => blockLoudness(zj) >= gammaA);
|
|
280
|
+
if (aboveAbs.length === 0)
|
|
281
|
+
return Number.NEGATIVE_INFINITY;
|
|
282
|
+
const meanAbs = aboveAbs.reduce((s, v) => s + v, 0) / aboveAbs.length;
|
|
283
|
+
// Relative gate.
|
|
284
|
+
const gammaR = blockLoudness(meanAbs) - 10.0;
|
|
285
|
+
const aboveRel = z.filter((zj) => blockLoudness(zj) > gammaR && blockLoudness(zj) > gammaA);
|
|
286
|
+
if (aboveRel.length === 0)
|
|
287
|
+
return Number.NEGATIVE_INFINITY;
|
|
288
|
+
const meanRel = aboveRel.reduce((s, v) => s + v, 0) / aboveRel.length;
|
|
289
|
+
return -0.691 + 10 * Math.log10(meanRel);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Calculate the loudness level of audio data using ITU-R BS.1770.
|
|
293
|
+
*
|
|
294
|
+
* @param audio Audio data as raw bytes (16-bit signed integers). Must hold at
|
|
295
|
+
* least 400ms of audio, the length of a BS.1770 gating block.
|
|
296
|
+
* @param sampleRate Sample rate of the audio in Hz.
|
|
297
|
+
* @returns Normalized loudness value between 0 (quiet) and 1 (loud).
|
|
298
|
+
* @throws Error if the audio is shorter than a gating block.
|
|
299
|
+
*/
|
|
300
|
+
export function calculateAudioVolume(audio, sampleRate) {
|
|
301
|
+
const audioNp = bytesToInt16(audio);
|
|
302
|
+
const audioFloat = new Float64Array(audioNp.length);
|
|
303
|
+
for (let i = 0; i < audioNp.length; i++) {
|
|
304
|
+
audioFloat[i] = Math.fround(audioNp[i] / 32768.0);
|
|
305
|
+
}
|
|
306
|
+
let level = integratedLoudness(audioFloat, sampleRate);
|
|
307
|
+
// Loudness goes from -110 to -10 LUFS (more or less), where -110 is quiet
|
|
308
|
+
// and -10 is loud. Audio below the BS.1770 absolute gate measures as -inf,
|
|
309
|
+
// which normalizes to 0.
|
|
310
|
+
level = normalizeValue(level, -110, -10);
|
|
311
|
+
return level;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Apply exponential smoothing to a value.
|
|
315
|
+
*
|
|
316
|
+
* Exponential smoothing is used to reduce noise in time-series data by giving
|
|
317
|
+
* more weight to recent values while still considering historical data.
|
|
318
|
+
*
|
|
319
|
+
* @param value The new value to incorporate.
|
|
320
|
+
* @param prevValue The previous smoothed value.
|
|
321
|
+
* @param factor Smoothing factor between 0 and 1. Higher values give more
|
|
322
|
+
* weight to the new value.
|
|
323
|
+
* @returns The exponentially smoothed value.
|
|
324
|
+
*/
|
|
325
|
+
export function expSmoothing(value, prevValue, factor) {
|
|
326
|
+
return prevValue + factor * (value - prevValue);
|
|
327
|
+
}
|
|
328
|
+
//
|
|
329
|
+
// G.711 codecs (replaces Python's `audioop`; same algorithms as CPython).
|
|
330
|
+
//
|
|
331
|
+
const SEG_UEND = [0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff];
|
|
332
|
+
const SEG_AEND = [0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff];
|
|
333
|
+
const BIAS = 0x84;
|
|
334
|
+
const CLIP = 32635;
|
|
335
|
+
function search(value, table) {
|
|
336
|
+
for (let i = 0; i < table.length; i++) {
|
|
337
|
+
if (value <= table[i])
|
|
338
|
+
return i;
|
|
339
|
+
}
|
|
340
|
+
return table.length;
|
|
341
|
+
}
|
|
342
|
+
function linear14ToUlaw(pcmVal) {
|
|
343
|
+
let mask;
|
|
344
|
+
if (pcmVal < 0) {
|
|
345
|
+
pcmVal = -pcmVal;
|
|
346
|
+
mask = 0x7f;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
mask = 0xff;
|
|
350
|
+
}
|
|
351
|
+
if (pcmVal > CLIP)
|
|
352
|
+
pcmVal = CLIP;
|
|
353
|
+
pcmVal += BIAS >> 2;
|
|
354
|
+
const seg = search(pcmVal, SEG_UEND);
|
|
355
|
+
if (seg >= 8)
|
|
356
|
+
return (0x7f ^ mask) & 0xff;
|
|
357
|
+
const uval = (seg << 4) | ((pcmVal >> (seg + 1)) & 0xf);
|
|
358
|
+
return (uval ^ mask) & 0xff;
|
|
359
|
+
}
|
|
360
|
+
function ulawToLinear16(uVal) {
|
|
361
|
+
uVal = ~uVal & 0xff;
|
|
362
|
+
let t = ((uVal & 0xf) << 3) + BIAS;
|
|
363
|
+
t <<= (uVal & 0x70) >> 4;
|
|
364
|
+
return uVal & 0x80 ? BIAS - t : t - BIAS;
|
|
365
|
+
}
|
|
366
|
+
function linear13ToAlaw(pcmVal) {
|
|
367
|
+
let mask;
|
|
368
|
+
if (pcmVal >= 0) {
|
|
369
|
+
mask = 0xd5;
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
mask = 0x55;
|
|
373
|
+
pcmVal = -pcmVal - 1;
|
|
374
|
+
}
|
|
375
|
+
const seg = search(pcmVal, SEG_AEND);
|
|
376
|
+
if (seg >= 8)
|
|
377
|
+
return (0x7f ^ mask) & 0xff;
|
|
378
|
+
let aval = seg << 4;
|
|
379
|
+
if (seg < 2)
|
|
380
|
+
aval |= (pcmVal >> 1) & 0xf;
|
|
381
|
+
else
|
|
382
|
+
aval |= (pcmVal >> seg) & 0xf;
|
|
383
|
+
return (aval ^ mask) & 0xff;
|
|
384
|
+
}
|
|
385
|
+
function alawToLinear16(aVal) {
|
|
386
|
+
aVal ^= 0x55;
|
|
387
|
+
let t = (aVal & 0xf) << 4;
|
|
388
|
+
const seg = (aVal & 0x70) >> 4;
|
|
389
|
+
switch (seg) {
|
|
390
|
+
case 0:
|
|
391
|
+
t += 8;
|
|
392
|
+
break;
|
|
393
|
+
case 1:
|
|
394
|
+
t += 0x108;
|
|
395
|
+
break;
|
|
396
|
+
default:
|
|
397
|
+
t += 0x108;
|
|
398
|
+
t <<= seg - 1;
|
|
399
|
+
}
|
|
400
|
+
return aVal & 0x80 ? t : -t;
|
|
401
|
+
}
|
|
402
|
+
function ulaw2lin(ulaw) {
|
|
403
|
+
const out = new Int16Array(ulaw.length);
|
|
404
|
+
for (let i = 0; i < ulaw.length; i++)
|
|
405
|
+
out[i] = ulawToLinear16(ulaw[i]);
|
|
406
|
+
return int16ToBytes(out);
|
|
407
|
+
}
|
|
408
|
+
function lin2ulaw(pcm) {
|
|
409
|
+
const samples = bytesToInt16(pcm);
|
|
410
|
+
const out = new Uint8Array(samples.length);
|
|
411
|
+
for (let i = 0; i < samples.length; i++)
|
|
412
|
+
out[i] = linear14ToUlaw(samples[i] >> 2);
|
|
413
|
+
return out;
|
|
414
|
+
}
|
|
415
|
+
function alaw2lin(alaw) {
|
|
416
|
+
const out = new Int16Array(alaw.length);
|
|
417
|
+
for (let i = 0; i < alaw.length; i++)
|
|
418
|
+
out[i] = alawToLinear16(alaw[i]);
|
|
419
|
+
return int16ToBytes(out);
|
|
420
|
+
}
|
|
421
|
+
function lin2alaw(pcm) {
|
|
422
|
+
const samples = bytesToInt16(pcm);
|
|
423
|
+
const out = new Uint8Array(samples.length);
|
|
424
|
+
for (let i = 0; i < samples.length; i++)
|
|
425
|
+
out[i] = linear13ToAlaw(samples[i] >> 3);
|
|
426
|
+
return out;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Convert μ-law encoded audio to PCM and optionally resample.
|
|
430
|
+
*
|
|
431
|
+
* @param ulawBytes μ-law encoded audio data as raw bytes.
|
|
432
|
+
* @param inRate Original sample rate of the μ-law audio in Hz.
|
|
433
|
+
* @param outRate Desired output sample rate in Hz.
|
|
434
|
+
* @param resampler Audio resampler instance for rate conversion.
|
|
435
|
+
* @returns PCM audio data as raw bytes at the specified output rate.
|
|
436
|
+
*/
|
|
437
|
+
export async function ulawToPcm(ulawBytes, inRate, outRate, resampler) {
|
|
438
|
+
// Convert μ-law to PCM
|
|
439
|
+
const inPcmBytes = ulaw2lin(ulawBytes);
|
|
440
|
+
// Resample
|
|
441
|
+
const outPcmBytes = await resampler.resample(inPcmBytes, inRate, outRate);
|
|
442
|
+
return outPcmBytes;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Convert PCM audio to μ-law encoding and optionally resample.
|
|
446
|
+
*
|
|
447
|
+
* @param pcmBytes PCM audio data as raw bytes (16-bit signed integers).
|
|
448
|
+
* @param inRate Original sample rate of the PCM audio in Hz.
|
|
449
|
+
* @param outRate Desired output sample rate in Hz.
|
|
450
|
+
* @param resampler Audio resampler instance for rate conversion.
|
|
451
|
+
* @returns μ-law encoded audio data as raw bytes at the specified output rate.
|
|
452
|
+
*/
|
|
453
|
+
export async function pcmToUlaw(pcmBytes, inRate, outRate, resampler) {
|
|
454
|
+
// Resample
|
|
455
|
+
const inPcmBytes = await resampler.resample(pcmBytes, inRate, outRate);
|
|
456
|
+
// Convert PCM to μ-law
|
|
457
|
+
const outUlawBytes = lin2ulaw(inPcmBytes);
|
|
458
|
+
return outUlawBytes;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Convert A-law encoded audio to PCM and optionally resample.
|
|
462
|
+
*
|
|
463
|
+
* @param alawBytes A-law encoded audio data as raw bytes.
|
|
464
|
+
* @param inRate Original sample rate of the A-law audio in Hz.
|
|
465
|
+
* @param outRate Desired output sample rate in Hz.
|
|
466
|
+
* @param resampler Audio resampler instance for rate conversion.
|
|
467
|
+
* @returns PCM audio data as raw bytes at the specified output rate.
|
|
468
|
+
*/
|
|
469
|
+
export async function alawToPcm(alawBytes, inRate, outRate, resampler) {
|
|
470
|
+
// Convert a-law to PCM
|
|
471
|
+
const inPcmBytes = alaw2lin(alawBytes);
|
|
472
|
+
// Resample
|
|
473
|
+
const outPcmBytes = await resampler.resample(inPcmBytes, inRate, outRate);
|
|
474
|
+
return outPcmBytes;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Convert PCM audio to A-law encoding and optionally resample.
|
|
478
|
+
*
|
|
479
|
+
* @param pcmBytes PCM audio data as raw bytes (16-bit signed integers).
|
|
480
|
+
* @param inRate Original sample rate of the PCM audio in Hz.
|
|
481
|
+
* @param outRate Desired output sample rate in Hz.
|
|
482
|
+
* @param resampler Audio resampler instance for rate conversion.
|
|
483
|
+
* @returns A-law encoded audio data as raw bytes at the specified output rate.
|
|
484
|
+
*/
|
|
485
|
+
export async function pcmToAlaw(pcmBytes, inRate, outRate, resampler) {
|
|
486
|
+
// Resample
|
|
487
|
+
const inPcmBytes = await resampler.resample(pcmBytes, inRate, outRate);
|
|
488
|
+
// Convert PCM to A-law
|
|
489
|
+
const outAlawBytes = lin2alaw(inPcmBytes);
|
|
490
|
+
return outAlawBytes;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Determine if an audio sample contains silence by checking amplitude levels.
|
|
494
|
+
*
|
|
495
|
+
* Analyzes raw PCM audio data to detect silence by comparing the maximum
|
|
496
|
+
* absolute amplitude against a predefined threshold. The audio is expected to
|
|
497
|
+
* be clean speech or complete silence without background noise.
|
|
498
|
+
*
|
|
499
|
+
* Normal speech typically produces amplitude values between ±500 to ±5000,
|
|
500
|
+
* depending on factors like loudness and microphone gain. The threshold
|
|
501
|
+
* (SPEAKING_THRESHOLD) is set well below typical speech levels to reliably
|
|
502
|
+
* detect silence vs. speech.
|
|
503
|
+
*
|
|
504
|
+
* @param pcmBytes Raw PCM audio data as bytes (16-bit signed integers).
|
|
505
|
+
* @returns True if the audio sample is considered silence (below threshold),
|
|
506
|
+
* false otherwise.
|
|
507
|
+
*/
|
|
508
|
+
export function isSilence(pcmBytes) {
|
|
509
|
+
// Read raw audio bytes as int16 samples
|
|
510
|
+
const audioData = bytesToInt16(pcmBytes);
|
|
511
|
+
if (audioData.length === 0) {
|
|
512
|
+
// numpy's max() of an empty array raises.
|
|
513
|
+
throw new Error("zero-size array to reduction operation maximum which has no identity");
|
|
514
|
+
}
|
|
515
|
+
// Check the maximum absolute amplitude in the frame
|
|
516
|
+
let maxValue = 0;
|
|
517
|
+
for (let i = 0; i < audioData.length; i++) {
|
|
518
|
+
const v = Math.abs(audioData[i]);
|
|
519
|
+
if (v > maxValue)
|
|
520
|
+
maxValue = v;
|
|
521
|
+
}
|
|
522
|
+
// If max value is lower than SPEAKING_THRESHOLD, consider it as silence
|
|
523
|
+
return maxValue <= SPEAKING_THRESHOLD;
|
|
524
|
+
}
|
|
525
|
+
/** Python's round(): half to even. */
|
|
526
|
+
function pyRound(x) {
|
|
527
|
+
const r = Math.round(x);
|
|
528
|
+
return Math.abs(x % 1) === 0.5 && r % 2 !== 0 ? r - 1 : r;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Detect the first sample of sustained audible speech in PCM audio.
|
|
532
|
+
*
|
|
533
|
+
* Measures short-time RMS energy: the signal is downmixed to mono, scanned
|
|
534
|
+
* with a `frameMs` window hopping every `hopMs`, and each window's RMS is
|
|
535
|
+
* computed with its mean removed (a DC offset carries no energy). Onset is the
|
|
536
|
+
* start of the first run of windows whose RMS stays above `thresholdDb` for at
|
|
537
|
+
* least `minVoicedMs`.
|
|
538
|
+
*
|
|
539
|
+
* Working on energy rather than per-sample amplitude rejects noise-floor blips
|
|
540
|
+
* (a lone loud sample averages out over the window), and the minimum-duration
|
|
541
|
+
* requirement rejects brief transients. `hopMs` sets the onset resolution.
|
|
542
|
+
*
|
|
543
|
+
* Operates on a growing buffer as audio streams in: returns null until enough
|
|
544
|
+
* audio has arrived to confirm an onset, at which point the caller stops
|
|
545
|
+
* feeding it.
|
|
546
|
+
*
|
|
547
|
+
* @param pcmBytes Raw PCM audio data (16-bit signed integers).
|
|
548
|
+
* @param sampleRate Sample rate of the audio in Hz.
|
|
549
|
+
* @param numChannels Number of interleaved audio channels (downmixed to mono).
|
|
550
|
+
* @returns The per-channel sample index of speech onset, or null if no
|
|
551
|
+
* sustained onset is present yet.
|
|
552
|
+
*/
|
|
553
|
+
export function detectSpeechOnset(pcmBytes, sampleRate, numChannels = 1, options = {}) {
|
|
554
|
+
const frameMs = options.frameMs ?? 10.0;
|
|
555
|
+
const hopMs = options.hopMs ?? 1.0;
|
|
556
|
+
const thresholdDb = options.thresholdDb ?? -40.0;
|
|
557
|
+
const minVoicedMs = options.minVoicedMs ?? 50.0;
|
|
558
|
+
if (sampleRate <= 0) {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
// A trailing partial sample can't be read as int16; ignore it.
|
|
562
|
+
const samples = bytesToInt16(pcmBytes.subarray(0, pcmBytes.length & ~1));
|
|
563
|
+
if (samples.length === 0) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
// Downmix to a mono signal normalized to [-1, 1], keeping the sign so that
|
|
567
|
+
// mean-removed RMS measures energy correctly.
|
|
568
|
+
let mono;
|
|
569
|
+
if (numChannels > 1) {
|
|
570
|
+
const usable = samples.length - (samples.length % numChannels);
|
|
571
|
+
mono = new Float32Array(usable / numChannels);
|
|
572
|
+
for (let i = 0; i < mono.length; i++) {
|
|
573
|
+
let sum = 0;
|
|
574
|
+
for (let c = 0; c < numChannels; c++)
|
|
575
|
+
sum += samples[i * numChannels + c];
|
|
576
|
+
mono[i] = sum / numChannels;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
mono = Float32Array.from(samples);
|
|
581
|
+
}
|
|
582
|
+
for (let i = 0; i < mono.length; i++)
|
|
583
|
+
mono[i] = mono[i] / 32768.0;
|
|
584
|
+
const n = mono.length;
|
|
585
|
+
const frame = Math.max(1, pyRound((sampleRate * frameMs) / 1000));
|
|
586
|
+
const hop = Math.max(1, pyRound((sampleRate * hopMs) / 1000));
|
|
587
|
+
if (n < frame) {
|
|
588
|
+
// Not enough audio for even one window; wait for more.
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
const gate = 10.0 ** (thresholdDb / 20.0); // normalized RMS gate (-40 dBFS = 0.01)
|
|
592
|
+
// Edge-pad so each window stays centered on its hop position and a constant
|
|
593
|
+
// start isn't read as a step (which would carry energy).
|
|
594
|
+
const pad = Math.floor(frame / 2);
|
|
595
|
+
const padded = new Float32Array(n + 2 * pad);
|
|
596
|
+
padded.fill(mono[0], 0, pad);
|
|
597
|
+
padded.set(mono, pad);
|
|
598
|
+
padded.fill(mono[n - 1], pad + n);
|
|
599
|
+
const numWindows = padded.length - frame + 1;
|
|
600
|
+
const active = [];
|
|
601
|
+
for (let start = 0; start < numWindows; start += hop) {
|
|
602
|
+
let mean = 0;
|
|
603
|
+
for (let i = 0; i < frame; i++)
|
|
604
|
+
mean += padded[start + i];
|
|
605
|
+
mean /= frame;
|
|
606
|
+
let sq = 0;
|
|
607
|
+
for (let i = 0; i < frame; i++) {
|
|
608
|
+
const d = padded[start + i] - mean;
|
|
609
|
+
sq += d * d;
|
|
610
|
+
}
|
|
611
|
+
active.push(Math.sqrt(sq / frame) > gate);
|
|
612
|
+
}
|
|
613
|
+
if (!active.some((a) => a)) {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
// Onset is the start of the first run of active windows lasting at least
|
|
617
|
+
// minVoicedMs. A window spreads a lone sample across ~frameMs, so
|
|
618
|
+
// minVoicedMs must exceed frameMs to tell a real onset from a blip.
|
|
619
|
+
const minWindows = Math.max(1, pyRound(minVoicedMs / hopMs));
|
|
620
|
+
let run = 0;
|
|
621
|
+
for (let i = 0; i < active.length; i++) {
|
|
622
|
+
if (active[i]) {
|
|
623
|
+
run += 1;
|
|
624
|
+
if (run >= minWindows) {
|
|
625
|
+
return (i - minWindows + 1) * hop;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
run = 0;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026, Daily
|
|
2
|
+
// Copyright (c) 2026, pipedog contributors
|
|
3
|
+
// SPDX-License-Identifier: BSD-2-Clause
|
|
4
|
+
//
|
|
5
|
+
// Ported from pipecat: src/pipecat/audio/vad/data/__init__.py
|
|
6
|
+
// Upstream's `__init__.py` is empty: import the package's modules directly.
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026, Daily
|
|
2
|
+
// Copyright (c) 2026, pipedog contributors
|
|
3
|
+
// SPDX-License-Identifier: BSD-2-Clause
|
|
4
|
+
//
|
|
5
|
+
// Ported from pipecat: src/pipecat/audio/vad/__init__.py
|
|
6
|
+
// Upstream's `__init__.py` is empty: import the package's modules directly.
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=index.js.map
|