> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.sleepcycle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS SDK

> 面向 iOS 应用的高级睡眠分析能力

# Sleep Cycle SDK - iOS 文档

## 概览

Sleep Cycle SDK for iOS 让开发者能够将先进的睡眠分析能力集成到他们的应用中。SDK 通过音频和运动传感器提供实时睡眠追踪，并在整夜过程中生成详细的睡眠洞察、睡眠阶段转换以及检测到的事件。

## 系统要求

最低 iOS 版本：

* iOS：16.0+
* macOS：13.0+

Swift：

* Swift 版本：5.9+
* SDK 使用 Swift 编写，并提供原生的 Swift API，支持 async/await

## 安装

### Swift Package Manager

使用 Swift Package Manager 将 Sleep Cycle SDK 添加到您的项目：

1. 在 Xcode 中选择 **File** → **Add Package Dependencies**
2. 输入 package URL：`https://github.com/MDLabs/sleepcycle-sdk-swift`
3. 选择您要使用的版本（语义化版本号）
4. 将该 package 添加到您的目标

也可以将其添加到 `Package.swift` 中：

```swift theme={null}
dependencies: [
    .package(url: "https://github.com/MDLabs/sleepcycle-sdk-swift", from: "1.2.0")
]
```

> SDK 需要 API 密钥用于授权。请联系 Sleep Cycle 获取凭证。

## 前置条件

### 权限

SDK 需要麦克风权限以进行基于音频的睡眠分析。请将以下内容添加到您的 `Info.plist`：

```xml theme={null}
<key>NSMicrophoneUsageDescription</key>
<string>We need access to the microphone to analyze your sleep patterns and detect snoring.</string>
```

如需基于运动的分析，您可能还需要：

```xml theme={null}
<key>NSMotionUsageDescription</key>
<string>We use motion data to track your sleep movements.</string>
```

### 后台模式

要确保整夜持续进行睡眠分析，请在应用的 capabilities 中启用相应的后台模式：

1. 在 Xcode 中打开您的项目
2. 选择应用的 target
3. 进入 "Signing & Capabilities"
4. 添加 "Background Modes" 能力
5. 启用 "Audio"

也可以将以下内容添加到 `Info.plist`：

```xml theme={null}
<key>UIBackgroundModes</key>
<array>
    <string>audio</string>
</array>
```

SDK 在睡眠分析期间使用音频后台模式来维持持续的音频处理。您的应用还应实现合适的会话管理，以防止 iOS 挂起分析进程。

## 通用说明

SDK 是线程安全的，所有异步操作均使用 Swift 并发（async/await）。

## 初始化 SDK

SDK 在使用前需要进行身份验证。初始化过程会校验您的凭证并确定可用的功能。

```swift theme={null}
import SleepCycleSDK

Task {
    do {
        let features = try await SleepCycleSdk.initialize(
            logLevel: .info,
            apiKey: "your-api-key-here"
        )
        print("Authorized with features: \(features)")
    } catch {
        print("Initialization error: \(error)")
    }
}
```

参数：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>logLevel</code> <span style={{ opacity: 0.5 }}>LogLevel</span> - SDK 日志详细程度（<code>.debug</code>、<code>.info</code>、<code>.warning</code>、<code>.error</code>、<code>.noLog</code>）<br />
  <code>logger</code> <span style={{ opacity: 0.5 }}>Logger?</span> - 可选的自定义日志记录器（默认为系统日志记录器）<br />
  <code>apiKey</code> <span style={{ opacity: 0.5 }}>String</span> - 您的 Sleep Cycle API 密钥<br />
  <code>forceTokenRefresh</code> <span style={{ opacity: 0.5 }}>Bool</span> - 即使存在缓存令牌也强制重新获取令牌（默认为 false）
</div>

返回的 `SleepAnalysisFeatures` 表示您的 API 密钥可用的能力：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>sleepStaging</code> <span style={{ opacity: 0.5 }}>Bool</span> - 睡眠分期分析<br />
  <code>smartAlarm</code> <span style={{ opacity: 0.5 }}>Bool</span> - 智能闹钟功能<br />
  <code>audioEvents</code> <span style={{ opacity: 0.5 }}>Bool</span> - 音频事件检测<br />
  <code>snoringDetection</code> <span style={{ opacity: 0.5 }}>Bool</span> - 鼾声检测<br />
  <code>realTimeSleepStaging</code> <span style={{ opacity: 0.5 }}>Bool</span> - 实时睡眠分期<br />
  <code>multiChannelAnalysis</code> <span style={{ opacity: 0.5 }}>Bool</span> - 多声道分析（立体声，两个声道）<br />
  <code>extendedAudioEvents</code> <span style={{ opacity: 0.5 }}>Bool</span> - 标准集之外的扩展音频事件类型
</div>

在运行时访问功能开关：

```swift theme={null}
if SleepCycleSdk.isFeatureEnabled(\.audioEvents) {
    // Present snore/talk event UI
}
```

## 获取 SDK 状态

通过 AsyncStream 监听 SDK 状态的变化：

```swift theme={null}
import SleepCycleSDK

Task {
    for await state in await SleepCycleSdk.stateStream {
        switch state {
        case .uninitialized:
            print("SDK not initialized")
        case .initialized:
            print("SDK ready")
        case .running:
            print("Analysis in progress")
        }
    }
}
```

获取当前状态：

```swift theme={null}
let currentState = await SleepCycleSdk.currentState
```

## 启动睡眠分析会话

初始化完成后，即可启动一次睡眠分析会话。该方法返回标识本次会话的 `UUID`。

```swift theme={null}
import SleepCycleSDK

Task {
    do {
        let sessionId: UUID = try await SleepCycleSdk.startAnalysis(
            config: SleepAnalysisConfig(
                useAudio: true,
                useAccelerometer: true
            )
        )
        print("Analysis started with session ID: \(sessionId)")
    } catch {
        print("Failed to start analysis: \(error)")
    }
}
```

参数：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>config</code> <span style={{ opacity: 0.5 }}>SleepAnalysisConfig</span> - 用于指定使用哪些传感器的配置对象<br />
  <code>at</code> <span style={{ opacity: 0.5 }}>Date</span> - 分析的起始时间（默认为当前时间）<br />
  <code>using</code> <span style={{ opacity: 0.5 }}>DataSource?</span> - 可选的数据源（例如实时或文件回放）<br />
  <code>eventListeners</code> <span style={{ opacity: 0.5 }}>\[AudioEventListener]</span> - 可选的监听器数组，在音频分析过程中接收回调。可用于实时捕获音频样本和事件
</div>

## 恢复会话

SDK 支持恢复先前启动的分析会话。当应用重启或后台任务被系统终止时，这一功能很有用。

```swift theme={null}
if await SleepCycleSdk.isResumePossible() {
    let resumedSessions: [ResumedSession] = try await SleepCycleSdk.resumeAnalysis()
    for session in resumedSessions {
        print("Resumed \(session.sessionId) on channel \(session.channel)")
    }
}
```

`resumeAnalysis()` 返回一个 `ResumedSession` 数组，每个元素包含所恢复会话的 `sessionId`、`channel` 以及任何已持久化的 `smartAlarmConfig`。

## 停止会话

要停止当前的分析会话并获取结果：

```swift theme={null}
Task {
    do {
        let result = try await SleepCycleSdk.stopAnalysis()

        print("Session ID: \(result.sessionId)")

        if let statistics = result.statistics {
            print("Total sleep duration: \(statistics.totalSleepDuration ?? 0)")
            print("Sleep efficiency: \(statistics.sleepEfficiency ?? 0)")

            if let snoreSessions = statistics.snoreSessions {
                for session in snoreSessions {
                    print("Snoring session: \(session.interval)")
                }
            }
        }

        for event in result.events {
            print("\(event.type) detected: \(event.interval), p=\(event.probability)")
        }

        for breathingRate in result.breathingRates {
            print("Breathing rate: \(breathingRate.bpm) bpm at \(breathingRate.timestamp)")
        }

        for stageInterval in result.sleepStageIntervals {
            print("\(stageInterval.stage): \(stageInterval.interval)")
        }

        if let audioStats = result.audioStatistics {
            for interval in audioStats.healthIntervals {
                print("Audio \(interval.status): \(interval.interval)")
            }
        }
    } catch {
        print("Failed to stop analysis: \(error)")
    }
}
```

## 分析结果

`AnalysisResult` 包含一次睡眠分析会话的完整输出：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 唯一会话标识符<br />
  <code>startTime</code> <span style={{ opacity: 0.5 }}>Date</span> - 会话起始时间<br />
  <code>endTime</code> <span style={{ opacity: 0.5 }}>Date</span> - 会话结束时间<br />
  <code>timeZone</code> <span style={{ opacity: 0.5 }}>TimeZone</span> - 会话开始时捕获的时区<br />
  <code>events</code> <span style={{ opacity: 0.5 }}>\[Event]</span> - 检测到的睡眠事件<br />
  <code>breathingRates</code> <span style={{ opacity: 0.5 }}>\[BreathingRate]</span> - 呼吸频率测量值<br />
  <code>sleepStageIntervals</code> <span style={{ opacity: 0.5 }}>\[SleepStageInterval]</span> - 睡眠阶段数据<br />
  <code>realTimeSleepStageIntervals</code> <span style={{ opacity: 0.5 }}>\[SleepStageInterval]</span> - 会话期间实时发出的睡眠分期<br />
  <code>statistics</code> <span style={{ opacity: 0.5 }}>SleepStatistics?</span> - 聚合的睡眠统计（可选）<br />
  <code>audioStatistics</code> <span style={{ opacity: 0.5 }}>AudioStatistics?</span> - 音频运行状况统计（可选）
</div>

### SleepStatistics

当存在时，`statistics` 包含本次睡眠会话的聚合指标：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>totalSleepDuration</code> <span style={{ opacity: 0.5 }}>Double?</span> - 总睡眠时长<br />
  <code>sleepOnsetLatency</code> <span style={{ opacity: 0.5 }}>Double?</span> - 入睡所用时间<br />
  <code>sleepEfficiency</code> <span style={{ opacity: 0.5 }}>Double?</span> - 睡眠时长与在床时长的比值（0.0 到 1.0）<br />
  <code>finalWakeTime</code> <span style={{ opacity: 0.5 }}>Date?</span> - 最终醒来时间<br />
  <code>numberOfAwakenings</code> <span style={{ opacity: 0.5 }}>Int?</span> - 整夜的醒来次数<br />
  <code>snoreTime</code> <span style={{ opacity: 0.5 }}>Double?</span> - 鼾声总时长<br />
  <code>snoreSessions</code> <span style={{ opacity: 0.5 }}>\[SnoreSession]?</span> - 单次鼾声会话<br />
  <code>sleepStageDurations</code> <span style={{ opacity: 0.5 }}>\[SleepStage: Double]?</span> - 每个睡眠阶段的时长
</div>

### AudioStatistics

当存在时，`audioStatistics` 包含整个会话期间音频输入运行状况的相关信息。

## 睡眠评分

会话完成后，您可以使用 `SleepScoring.compute(result:history:dateOfBirth:chronoType:)` 计算当晚的睡眠评分。该评分将当晚的结果与最近几晚的简短历史记录结合起来。

```swift theme={null}
import SleepCycleSDK

// 从每个已完成的结果构建历史记录条目，并将其持久化以供后续夜晚使用
let historyEntry = result.toSleepScoreHistoryEntry()

let score = SleepScoring.compute(
    result: result,
    history: recentHistoryEntries,
    dateOfBirth: userDateOfBirth,   // 可选，按年龄调整质量子评分
    chronoType: userChronoType      // 可选，选择时段子评分的窗口
)

print("Sleep score: \(score.total) (duration=\(score.duration), quality=\(score.quality), routine=\(score.routine))")
```

每个 `SleepScore` 字段的取值范围为 0.0–1.0，数值越高越好：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>total</code> <span style={{ opacity: 0.5 }}>Float</span> - 当晚的总体睡眠评分<br />
  <code>duration</code> <span style={{ opacity: 0.5 }}>Float</span> - 用户的睡眠时长<br />
  <code>quality</code> <span style={{ opacity: 0.5 }}>Float</span> - 用户的睡眠质量<br />
  <code>routine</code> <span style={{ opacity: 0.5 }}>Float</span> - 用户的睡眠作息
</div>

`SleepScoring.identifyChronoType(history:)` 根据最近的历史记录推导用户的 `ChronoType`（`.extremeMorning`、`.morning`、`.intermediate`、`.evening`、`.extremeEvening`），数据不足时返回 `nil`。其结果可作为 `chronoType` 参数传回 `compute(...)`。

## 实时事件

SDK 在分析过程中通过 AsyncStream API 提供实时事件更新：

```swift theme={null}
Task {
    for await events in await SleepCycleSdk.eventStream {
        for event in events {
            switch event.type {
            case .movement:
                handleMovement(event)
            case .snoring:
                handleSnoring(event)
            case .talking:
                handleTalking(event)
            case .coughing:
                handleCoughing(event)
            default:
                handleOtherEvent(event)
            }
        }
    }
}
```

当您的 API 密钥启用了 `extendedAudioEvents` 功能时，会在标准事件之外同时报告额外的 `EventType` 值：`.bird`、`.cat`、`.digestive`、`.dog`、`.fart`、`.music`、`.sneeze`、`.throatClearing`、`.traffic`、`.water` 和 `.wind`。使用 `EventType.standardTypes` 和 `EventType.extendedTypes` 来区分这两个集合。

每个 `Event` 包含：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>type</code> <span style={{ opacity: 0.5 }}>EventType</span> - 事件类型<br />
  <code>interval</code> <span style={{ opacity: 0.5 }}>DateInterval</span> - 事件的时间区间<br />
  <code>probability</code> <span style={{ opacity: 0.5 }}>Double</span> - 置信度分数（0.0 到 1.0）<br />
  <code>source</code> <span style={{ opacity: 0.5 }}>EventSource</span> - 检测来源<br />
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 该事件所属的会话<br />
  <code>signature</code> <span style={{ opacity: 0.5 }}>\[Float]?</span> - 可选特征向量(用于鼾声事件)
</div>

## 实时呼吸频率

SDK 在分析过程中提供实时呼吸频率测量：

```swift theme={null}
Task {
    for await breathingRate in await SleepCycleSdk.breathingRateStream {
        print("Breathing rate: \(breathingRate.bpm) bpm (confidence: \(breathingRate.confidence))")
    }
}
```

每个 `BreathingRate` 包含：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>timestamp</code> <span style={{ opacity: 0.5 }}>Date</span> - 测量记录的时间<br />
  <code>bpm</code> <span style={{ opacity: 0.5 }}>Double</span> - 呼吸频率（每分钟呼吸次数）<br />
  <code>confidence</code> <span style={{ opacity: 0.5 }}>Double</span> - 测量的置信度（0.0 到 1.0）<br />
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 该测量所属的会话
</div>

### 实时睡眠分期（实验性）

<Warning>
  此功能为实验性功能，未来版本中可能会发生变更。API 和行为可能在未通知的情况下被修改。
</Warning>

SDK 可在分析过程中提供实时睡眠阶段预测。此功能要求您的 API 密钥启用了 `realTimeSleepStaging` 功能。

```swift theme={null}
Task {
    for await stageInterval in await SleepCycleSdk.sleepStageStream {
        switch stageInterval.stage {
        case .awake:
            print("Awake: \(stageInterval.interval)")
        case .light:
            print("Light sleep: \(stageInterval.interval)")
        case .deep:
            print("Deep sleep: \(stageInterval.interval)")
        case .rem:
            print("REM sleep: \(stageInterval.interval)")
        }
    }
}
```

该流在分析过程中大约每 30 秒发出一个 `SleepStageInterval` 对象，从而以接近实时的方式反馈睡眠状态的转换。

### 实时音频运行状况

SDK 在分析期间监测音频输入的运行状况，并在状态变化时发出更新：

```swift theme={null}
Task {
    for await update in await SleepCycleSdk.audioHealthStream {
        switch update.status {
        case .healthy:
            print("Audio input healthy")
        case .flatline:
            print("Audio flatline detected")
        case .missingInput:
            print("Audio input missing")
        }
    }
}
```

`AudioHealthStatus` 取值：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>.healthy</code> - 音频输入包含有变化的信号<br />
  <code>.flatline</code> - 检测到恒定值（麦克风失效或输入静音）<br />
  <code>.missingInput</code> - 较长时间内未收到任何音频输入
</div>

## 智能闹钟

智能闹钟在唤醒时段内监测身体活动，并在用户处于浅睡眠阶段时发出事件，从而让您在最佳时机唤醒用户。这需要为您的 API 密钥启用 `smartAlarm` 功能，且仅在主声道上支持。

使用 `SmartAlarmConfig` 配置唤醒时段，并在开始分析时传入：

```swift theme={null}
import SleepCycleSDK

let wakeupWindow = DateInterval(start: windowStart, end: windowEnd)

try await SleepCycleSdk.startAnalysis(
    config: SleepAnalysisConfig(useAudio: true, useAccelerometer: true),
    smartAlarmConfig: SmartAlarmConfig(wakeupWindow: wakeupWindow)
)
```

通过 `smartAlarmStream` 观察闹钟生命周期事件：

```swift theme={null}
Task {
    for await event in await SleepCycleSdk.smartAlarmStream {
        switch event.type {
        case .armed:
            print("Smart alarm armed")
        case .triggered(let reason):
            switch reason {
            case .optimalWakeUp, .userInteraction, .windowEnd:
                ringAlarm()
            }
        }
    }
}
```

`smartAlarmConfig` 参数在 `startMultiChannelAnalysis(...)` 上同样可用。

## 事件签名

对于鼾声事件，`Event.signature` 属性包含一个 16 维特征向量，表示所检测到鼾声的独特特征。来自同一人的鼾声事件在签名空间中彼此聚集，因此可以按人对事件进行聚类。

## 音频事件监听器

`AudioEventListener` 协议允许您在会话过程中接收实时的音频分析更新。实现该协议可在分析进行时访问原始音频样本、事件检测以及音量信息。

```swift theme={null}
class MyAudioListener: AudioEventListener {
    func onAudioAnalysisBatchCompleted(
        sessionId: UUID,
        audioSamples: [Float],
        audioSampleRate: Int,
        audioStartTime: Date,
        audioEndTime: Date,
        audioProbability: [EventType: Float],
        eventsStarted: [EventStartedInfo],
        eventsEnded: [EventEndedInfo],
        dbSpl: [Float]
    ) {
        // Process audio samples and events
    }
}

let listener = MyAudioListener()
try await SleepCycleSdk.startAnalysis(
    config: SleepAnalysisConfig(useAudio: true),
    eventListeners: [listener]
)
```

`audioSamples` 参数顺序包含所有已处理的音频数据，批次之间没有间隙或重叠。每个批次都从前一个批次结束的位置精确接续，从而对所有分析过的音频实现完整覆盖。

`audioProbability` 参数提供所分析时间窗口内每种 `EventType` 的每批次概率。`dbSpl` 参数提供批次中每个时间帧以 dB SPL 表示的 A 计权声音音量。

## 音频片段

当检测到特定的睡眠事件（例如鼾声、梦话或咳嗽）时，SDK 可以捕获短音频录音。

使用 `AudioClipsConfig` 和 `AudioClipsReceiver` 创建一个 `AudioEventListener`：

```swift theme={null}
import SleepCycleSDK

let listener = SleepCycleSdk.createAudioClipsProducer(
    audioClipsConfig: AudioClipsConfig(
        activeTypes: [
            .snoring: EventTypeConfig(minDuration: 0.5),
            .talking: EventTypeConfig(minDuration: 0.5)
        ],
        clipLength: 5.0
    ),
    receiver: MyAudioHandler()
)

try await SleepCycleSdk.startAnalysis(
    config: SleepAnalysisConfig(useAudio: true),
    eventListeners: [listener]
)
```

每个 `AudioClip` 包含：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>startTime</code> <span style={{ opacity: 0.5 }}>Date</span> - 起始时间戳<br />
  <code>type</code> <span style={{ opacity: 0.5 }}>EventType</span> - 触发本次捕获的事件类型<br />
  <code>samples</code> <span style={{ opacity: 0.5 }}>\[Float]</span> - 原始音频样本<br />
  <code>sampleRate</code> <span style={{ opacity: 0.5 }}>Int</span> - 采样率（Hz）<br />
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 该片段所属的会话
</div>

## 多声道分析

SDK 支持使用立体声音频源同时分析两个声道。多声道分析将数据源生命周期与各个会话生命周期分离，使您可以独立启动和停止每个声道上的会话。

立体声流应来自两个独立的单声道麦克风，每个麦克风占用一个声道，再合并为单个立体声流。

此功能要求您的 API 密钥启用了 `multiChannelAnalysis` 功能。

### 声道分离

使用立体声输入时，`ChannelSeparationConfig` 控制如何将音频事件分配到各个声道。内置预设：

* `.bedSideMics` — 分离放置的床头麦克风（默认值）
* `.centeredMicArray` — 间距很近的麦克风阵列
* `.detectionStrengthOnly()` — 不进行空间过滤，仅依据检测置信度

所有参数（麦克风间距、模糊区、置信度阈值、各事件类型设置）都可以单独调节，以适配您的具体硬件配置和使用场景。

### 数据源生命周期

在启动各个会话之前，使用立体声音频配置启动数据源：

```swift theme={null}
import SleepCycleSDK

let dataSource = SleepCycleSdk.createLiveDataSource()

try await SleepCycleSdk.startDataSource(
    using: dataSource,
    channelSeparationConfig: .bedSideMics
)
```

### 在每个声道上启动会话

数据源运行后，在每个声道上启动一个会话：

```swift theme={null}
let primarySessionId: UUID = try await SleepCycleSdk.startMultiChannelAnalysis(
    channel: .primary,
    config: SleepAnalysisConfig(useAudio: true, useAccelerometer: true)
)

let secondarySessionId: UUID = try await SleepCycleSdk.startMultiChannelAnalysis(
    channel: .secondary,
    config: SleepAnalysisConfig(useAudio: true, useAccelerometer: false)
)
```

`AnalysisChannel` 取值：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>.primary</code> - 第一个音频声道（或单声道）<br />
  <code>.secondary</code> - 立体声中的第二个音频声道
</div>

### 独立停止各个会话

每个会话都可以独立停止以获取其结果：

```swift theme={null}
let primaryResult = try await SleepCycleSdk.stopAnalysis(sessionId: primarySessionId)
let secondaryResult = try await SleepCycleSdk.stopAnalysis(sessionId: secondarySessionId)
```

### 停止数据源

所有会话都已停止后，再停止数据源：

```swift theme={null}
await SleepCycleSdk.stopDataSource()
```

如果在仍有会话处于活动状态时调用 `stopDataSource()`，会强制停止这些会话并丢弃其结果。要保留结果，请先停止每个会话。
