Typescript Example

iris-node-demo.ts

 1import {
 2  AudioContextRequest,
 3  ProgressEventType,
 4  ProgressEvent,
 5  ResamplerMode,
 6  cleanup,
 7  createAudioContext,
 8  init,
 9  processOffline,
10  releaseAudioContext,
11} from 'iris-sdk';
12import { writeFile } from 'node:fs/promises';
13import {
14  checkContextConfig,
15  checkContextRequest,
16  checkLicenseInfo,
17  rawToArray,
18} from './demoUtils';
19
20function processCallback(event: ProgressEvent) {
21  switch (event.type) {
22    case ProgressEventType.START:
23      console.log('Processing: started');
24      break;
25    case ProgressEventType.PROCESS:
26      process.stdout.write(`\rProcessing: ${event.percentage.toFixed(2)}%`);
27      break;
28    case ProgressEventType.END:
29      console.log('\nProcessing: ended');
30      break;
31  }
32}
33
34(async () => {
35  // initialise iris sdk. either pass in the licence and key as strings or let the sdk discover
36  // them from its default data location. See readme.md for default locations
37  // const licence = await fileToString('/full/path/to/iris.lic');
38  // const key = await fileToString('/full/path/to/iris.key');
39  // const info = init(licence, key);
40  const info = init();
41
42  console.log(`Initialised iris-sdk ${info.version} for ${info.name}`);
43  checkLicenseInfo(info);
44
45  const filePath = './breaking_point_f32_48k.raw';
46  // Load a raw file;
47  const audioIn = await rawToArray(filePath);
48  const audioOut = new Float32Array(audioIn).fill(0);
49
50  const contextRequest: AudioContextRequest = {
51    processors: ['passthrough'],
52    sampleRate: 48000,
53    channelCount: 1,
54    resamplerMode: ResamplerMode.HQ,
55  };
56  checkContextRequest(contextRequest);
57
58  const config = createAudioContext(contextRequest);
59  checkContextConfig(config);
60
61  // Process the entire buffer in one go, accounting for any transport delay
62  // If processing a stream, call iris.sdk.process when each new buffer of stream data arrives instead
63  // In the streaming case, frames should be set to the size of the stream buffer size.
64  // If each buffer is the same size, set fixed_frame_count to true in the context request
65  // If the stream buffer size is known up front, set the buffer size in the context request
66  // streaming pseudocode
67  // while new_stream_data_available:
68  //   process_in_buffer = get_stream_source()
69  //   process_out_buffer = np.zeros_like(process_in_buffer, dtype=np.float32)
70  //   iris.sdk.process(config.context_id, process_in_buffer, process_out_buffer, len(process_in_buffer))
71  //   put_stream_sink(process_out_buffer)
72
73  console.log(`\nProcessing ${filePath}`);
74  processOffline(
75    config.contextId,
76    audioIn,
77    audioOut,
78    audioIn.length,
79    processCallback
80  );
81  // save the processed output
82  // audacity import raw data -> encoding 32 bit float / sample rate 48000
83  await writeFile('./breaking_point_f32_48k_processed.raw', audioOut);
84
85  // Release the context
86  console.log('Cleaning up...');
87  releaseAudioContext(config.contextId);
88  cleanup();
89  console.log('Done.');
90})();

demoUtils.ts

 1import {
 2  AudioContextConfig,
 3  AudioContextRequest,
 4  ErrorCodes,
 5  Info,
 6} from 'iris-sdk';
 7
 8import { readFile } from 'node:fs/promises';
 9
10export async function rawToArray(filePath: string) {
11  const data = await readFile(filePath);
12  // Interpret the buffer as Float32 values
13  const floatArray = new Float32Array(
14    data.buffer,
15    data.byteOffset,
16    data.byteLength / Float32Array.BYTES_PER_ELEMENT
17  );
18
19  // Convert the Float32 array to a string
20  return floatArray;
21}
22
23export function checkLicenseInfo(info: Info) {
24  console.log('\nLicence Info:');
25  console.log(`    Name: ${info.name}`);
26  console.log(`    SDK Version: ${info.version}`);
27  console.log(`    Expiry: ${info.expiry}`);
28  console.log(`    Licence status: ${info.status}\n`);
29  console.log(`Available processors: ${info.availableProcessors}\n`);
30
31  // Check licence is valid
32  if (info.status !== 'Licence valid') {
33    throw new Error(`Licence error: ${info.status}`);
34  }
35}
36
37export function checkContextRequest(request: AudioContextRequest) {
38  console.log('Audio Context Request:');
39  console.log(`    Sample rate: ${request.sampleRate}`);
40  console.log(`    Buffer length: ${request.bufferLength}`);
41  console.log(`    Processors: ${request.processors}`);
42  console.log(`    Resampler Mode: ${request.resamplerMode}`);
43  console.log(`    Optimisation: ${request.optimization}`);
44  console.log(`    Fixed frame count: ${request.fixedFrameCount}\n`);
45}
46
47export function checkContextConfig(config: AudioContextConfig) {
48  console.log(`Audio Context Configuration:`);
49  console.log(`    Context ID: ${config.contextId}`);
50  console.log(`    Description: ${config.description}`);
51  console.log(`    Sample rate: ${config.sampleRate}`);
52  console.log(`    Buffer length: ${config.bufferLength}`);
53  console.log(`    Channels: ${config.channelCount}`);
54  if (config.willResample) {
55    console.log(`    Resampling: ${config.willResample}`);
56    console.log(`    Resampler Mode: ${config.resamplerMode}`);
57  }
58  console.log(`    Optimisation: ${config.optimization}`);
59
60  if (config.error === ErrorCodes.NO_ERROR) {
61    console.log('    Context Parameters:');
62    for (const group of config.parameters) {
63      console.log(`        ${group.name}`);
64      for (const param of group.parameterDescriptions) {
65        console.log(`          -> ${param.name}`);
66      }
67    }
68  } else {
69    throw new Error(`Context creation failed: ${config.error}}`);
70  }
71}