| 8 | import { MINIMAP_FFT_SIZE } from '@/utils/constants'; |
| 9 | |
| 10 | export class BlobClient implements IQDataClient { |
| 11 | dataSources: Record<string, DataSource>; |
| 12 | |
| 13 | constructor(dataSources: Record<string, DataSource>) { |
| 14 | this.dataSources = dataSources; |
| 15 | } |
| 16 | |
| 17 | async getMinimapIQ(meta: SigMFMetadata, signal: AbortSignal): Promise<Float32Array[]> { |
| 18 | // Changes in the spectrogram height require a recalculation of the ffts required |
| 19 | // for minimap only. there's so much overhead with blob downloading that this might as well be a high value... |
| 20 | const skipNFfts = Math.floor(meta.getTotalSamples() / (1000 * MINIMAP_FFT_SIZE)); // sets the decimation rate (manually tweaked) |
| 21 | const numFfts = Math.floor(meta.getTotalSamples() / MINIMAP_FFT_SIZE / (skipNFfts + 1)); |
| 22 | let dataRange = []; |
| 23 | for (let i = 0; i < numFfts; i++) { |
| 24 | dataRange.push(i * skipNFfts); |
| 25 | } |
| 26 | const { account, container, file_path } = meta.getOrigin(); |
| 27 | const blobClient = getBlobClient(this.dataSources, account, container, file_path); |
| 28 | const iqBlocks: Float32Array[] = []; |
| 29 | for (const index of dataRange) { |
| 30 | const bytesPerSample = meta.getBytesPerIQSample(); |
| 31 | const offsetBytes = index * MINIMAP_FFT_SIZE * bytesPerSample; |
| 32 | const countBytes = MINIMAP_FFT_SIZE * bytesPerSample; |
| 33 | // This is ugly but it is the only way to get the blob as an ArrayBuffer |
| 34 | const download = await blobClient.download(offsetBytes, countBytes, { |
| 35 | abortSignal: signal, |
| 36 | }); |
| 37 | const blobBody = await (await download.blobBody).arrayBuffer(); |
| 38 | const iqArray = convertToFloat32(blobBody, meta.getDataType()); |
| 39 | iqBlocks.push(iqArray); |
| 40 | } |
| 41 | return iqBlocks; |
| 42 | } |
| 43 | |
| 44 | async getIQDataBlocks( |
| 45 | meta: SigMFMetadata, |
| 46 | indexes: number[], |
| 47 | blockSize: number, |
| 48 | signal: AbortSignal |
| 49 | ): Promise<IQDataSlice[]> { |
| 50 | console.debug('getIQDataBlocks', indexes); |
| 51 | const contiguousIndexes = groupContiguousIndexes(indexes); |
| 52 | let { account, container, file_path } = meta.getOrigin(); |
| 53 | // if filePath does not finish in .sigmf-data, add it |
| 54 | if (!file_path.endsWith('.sigmf-data')) { |
| 55 | file_path += '.sigmf-data'; |
| 56 | } |
| 57 | const content = await Promise.all( |
| 58 | contiguousIndexes.map((indexGroup) => |
| 59 | this.getIQDataBlockFromBlob( |
| 60 | getBlobClient(this.dataSources, account, container, file_path), |
| 61 | meta, |
| 62 | indexGroup.start, |
| 63 | indexGroup.count, |
| 64 | blockSize, |
| 65 | signal |
| 66 | ) |
| 67 | ) |
nothing calls this directly
no outgoing calls
no test coverage detected