Skip to content

Commit

Permalink
3.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
idranme committed Apr 23, 2024
1 parent 4e25e86 commit 91fe727
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 36 deletions.
45 changes: 38 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,49 @@ interface decodeResult {
data: Uint8Array
duration: number
}
```

```ts
// pcm 转 silk。input 为 wav 或单声道 pcm_s16le 文件,samplingRate 为 input 的采样率。
// sampleRate: 8000/12000/16000/24000/32000/44100/48000
/**
* 编码为 SILK
* @param input WAV 或单声道 pcm_s16le 文件
* @param sampleRate `input` 的采样率,可为 8000/12000/16000/24000/32000/44100/48000
* @return SILK
*/
function encode(input: ArrayBufferView | ArrayBuffer, sampleRate: number): Promise<encodeResult>

// silk 转 pcm。input 为 silk 文件,samplingRate 为 input 的采样率。
/**
* 将 SILK 解码为 PCM
* @param input SILK 文件
* @param sampleRate `input` 的采样率
* @return pcm_s16le
*/
function decode(input: ArrayBufferView | ArrayBuffer, sampleRate: number): Promise<decodeResult>

// 获取 silk 音频时长,输出单位为毫秒。
function getDuration(silk: ArrayBufferView | ArrayBuffer, frameMs?: number): number
/**
* 获取 SILK 音频时长
* @param data SILK 文件
* @param frameMs SILK 的 frameMs,可为 20/40/60/80/100,默认为 20
* @return 单位为毫秒的时长
*/
function getDuration(data: ArrayBufferView | ArrayBuffer, frameMs?: number): number

/**
* 检测是否为 WAV 文件
* @param data 任意文件
*/
function isWav(data: ArrayBufferView | ArrayBuffer): boolean

/**
* 获取 WAV 文件的信息
* @param data WAV 文件
* @return metadata
*/
function getWavFileInfo(data: ArrayBufferView | ArrayBuffer): WavFileInfo

/**
* 检测是否为 SILK 文件
* @param data 任意文件
*/
function isSilk(data: ArrayBufferView | ArrayBuffer): boolean
```

## Example
Expand Down
4 changes: 2 additions & 2 deletions binding/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.27)
cmake_minimum_required(VERSION 3.28)

## Project
project(silk_wasm)
Expand Down Expand Up @@ -36,7 +36,7 @@ add_library(silk
add_executable(${PROJECT_NAME} src/index.cpp)

set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-lembind -sALLOW_MEMORY_GROWTH -sMODULARIZE -sEXPORT_ES6 -sINVOKE_RUN=0 \
--closure 1 --embind-emit-tsd silk_wasm.d.ts")
--closure 1 --emit-tsd silk_wasm.d.ts")

target_include_directories(${PROJECT_NAME}
PRIVATE
Expand Down
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
{
"name": "silk-wasm",
"description": "Tencent silk encoder for Node.js and browser",
"version": "3.3.4",
"version": "3.4.0",
"main": "lib/index.cjs",
"module": "lib/index.mjs",
"typings": "lib/index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/idanran/silk-wasm.git"
"url": "git+https://github.com/idranme/silk-wasm.git"
},
"author": "idanran <[email protected]>",
"license": "MIT",
"files": [
"lib"
Expand All @@ -29,10 +28,13 @@
"codec"
],
"devDependencies": {
"@types/node": "^20.11.30",
"@types/node": "^20.12.7",
"esbuild": "^0.20.2",
"typescript": "^5.4.3",
"typescript": "^5.4.5",
"wav-file-decoder": "^1.0.3"
},
"packageManager": "[email protected]"
}
"packageManager": "[email protected]",
"engines": {
"node": ">=16.14.0"
}
}
57 changes: 49 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Instance from './silk_wasm.js'
import * as WavDecoder from 'wav-file-decoder'
import { concat, ensureMonoPcm, ensureS16lePcm } from './utils'
import { concat, ensureMonoPcm, ensureS16lePcm, toUTF8String } from './utils'

export interface encodeResult {
/** silk */
Expand Down Expand Up @@ -32,10 +32,18 @@ export interface WavFileInfo {
}
}

/**
* 编码为 SILK
* @param input WAV 或单声道 pcm_s16le 文件
* @param sampleRate `input` 的采样率,可为 8000/12000/16000/24000/32000/44100/48000
* @return SILK
*/
export async function encode(input: ArrayBufferView | ArrayBuffer, sampleRate: number): Promise<encodeResult> {
const instance = await Instance()
let buffer = ArrayBuffer.isView(input) ? input.buffer : input

if (buffer.byteLength === 0) throw new Error('input data length is 0')

if (WavDecoder.isWavFile(input)) {
const { channelData, sampleRate: wavSampleRate } = WavDecoder.decodeWavFile(input)
sampleRate ||= wavSampleRate
Expand Down Expand Up @@ -63,10 +71,18 @@ export async function encode(input: ArrayBufferView | ArrayBuffer, sampleRate: n
}
}

/**
* 将 SILK 解码为 PCM
* @param input SILK 文件
* @param sampleRate `input` 的采样率
* @return pcm_s16le
*/
export async function decode(input: ArrayBufferView | ArrayBuffer, sampleRate: number): Promise<decodeResult> {
const instance = await Instance()
const buffer = ArrayBuffer.isView(input) ? input.buffer : input

if (buffer.byteLength === 0) throw new Error('input data length is 0')

const arr: Uint8Array[] = []
let outputLength = 0

Expand All @@ -83,9 +99,15 @@ export async function decode(input: ArrayBufferView | ArrayBuffer, sampleRate: n
}
}

export function getDuration(silk: ArrayBufferView | ArrayBuffer, frameMs = 20): number {
const buffer = ArrayBuffer.isView(silk) ? silk.buffer : silk
const tencent = silk[0] === 0x02
/**
* 获取 SILK 音频时长
* @param data SILK 文件
* @param frameMs SILK 的 frameMs,可为 20/40/60/80/100,默认为 20
* @return 单位为毫秒的时长
*/
export function getDuration(data: ArrayBufferView | ArrayBuffer, frameMs = 20): number {
const buffer = ArrayBuffer.isView(data) ? data.buffer : data
const tencent = data[0] === 0x02
let offset = tencent ? 10 : 9
let blocks = 0
const view = new DataView(buffer)
Expand All @@ -97,10 +119,29 @@ export function getDuration(silk: ArrayBufferView | ArrayBuffer, frameMs = 20):
return blocks * frameMs
}

export function isWav(fileData: ArrayBufferView | ArrayBuffer): boolean {
return WavDecoder.isWavFile(fileData)
/**
* 检测是否为 WAV 文件
* @param data 任意文件
*/
export function isWav(data: ArrayBufferView | ArrayBuffer): boolean {
return WavDecoder.isWavFile(data)
}

/**
* 获取 WAV 文件的信息
* @param data WAV 文件
* @return metadata
*/
export function getWavFileInfo(data: ArrayBufferView | ArrayBuffer): WavFileInfo {
return WavDecoder.getWavFileInfo(data)
}

export function getWavFileInfo(fileData: ArrayBufferView | ArrayBuffer): WavFileInfo {
return WavDecoder.getWavFileInfo(fileData)
/**
* 检测是否为 SILK 文件
* @param data 任意文件
*/
export function isSilk(data: ArrayBufferView | ArrayBuffer): boolean {
const buffer = ArrayBuffer.isView(data) ? data.buffer : data
if (buffer.byteLength < 7) return false
return toUTF8String(buffer, 0, 7).includes('#!SILK')
}
22 changes: 22 additions & 0 deletions src/silk_wasm.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// TypeScript bindings for emscripten-generated code. Automatically generated at compile time.
declare namespace RuntimeExports {
let HEAPF64: any;
let HEAP_DATA_VIEW: any;
let HEAP8: any;
let HEAPU8: any;
let HEAP16: any;
let HEAPU16: any;
let HEAP32: any;
let HEAPU32: any;
let HEAP64: any;
let HEAPU64: any;
}
interface WasmModule {
}

interface EmbindModule {
silk_encode(_0: ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|string, _1: number, _2: number, _3: any): number;
silk_decode(_0: ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|string, _1: number, _2: number, _3: any): number;
}
export type MainModule = WasmModule & typeof RuntimeExports & EmbindModule;
export default function MainModuleFactory (options?: unknown): Promise<MainModule>;
Loading

0 comments on commit 91fe727

Please sign in to comment.