{"id":20078759,"url":"https://github.com/wpdas/digital-voyager-image-sound-core","last_synced_at":"2025-06-15T11:39:54.496Z","repository":{"id":223371634,"uuid":"253606296","full_name":"wpdas/digital-voyager-image-sound-core","owner":"wpdas","description":"Based on the Voyager Golden Record Disc. This module/software allows you to store and read data into/from an audio sample rates (WAV). Doesn't matter the kind, image, text, numbers, you can store and read it.","archived":false,"fork":false,"pushed_at":"2020-05-14T04:01:58.000Z","size":261,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-02T13:14:46.593Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wpdas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-04-06T20:18:29.000Z","updated_at":"2024-02-19T20:30:18.000Z","dependencies_parsed_at":"2024-02-19T22:53:41.675Z","dependency_job_id":null,"html_url":"https://github.com/wpdas/digital-voyager-image-sound-core","commit_stats":null,"previous_names":["wpdas/digital-voyager-image-sound-core"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wpdas/digital-voyager-image-sound-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpdas%2Fdigital-voyager-image-sound-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpdas%2Fdigital-voyager-image-sound-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpdas%2Fdigital-voyager-image-sound-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpdas%2Fdigital-voyager-image-sound-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wpdas","download_url":"https://codeload.github.com/wpdas/digital-voyager-image-sound-core/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpdas%2Fdigital-voyager-image-sound-core/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259967877,"owners_count":22939541,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T15:16:31.767Z","updated_at":"2025-06-15T11:39:54.471Z","avatar_url":"https://github.com/wpdas.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WAV File Header\n\nChecar aqui: https://wiki.fileformat.com/audio/wav/\n\nA header de um arquivo WAV leva 44 bytes;\nCada tom registrado pelo programa usa 176 bytes de informação (DIVISOR = 176 bytes, ZERO = 176 bytes, ONE = 176 bytes);\n\n- Lendo o cabeçalho (gerado por este software)\n\nAssim sendo, para se ler a Header (gerado por este software em ondas de bits), deve-se ler os 44 bytes do formato WAV a fim de ter o arquivo decodificado + 176 bytes x a quantidade de bits do `typeId`(8 bits). Ou seja: 44 + (176 x 8);\n\n# Sobre\n\nA ideia geral começou a partir do momento que o Disco de Ouro do Voyager foi assunto de interesse. Eu começei a tentar entender como os dados foram guardados e como poderiam ser interpretados. Bem, essa é uma versão diferente que se baseia em bits.\n\nPadrão na arquitetura de escrita e leitura: CD's digitais. Colocam um divisor entre cada bit. O projeto inteiro trata apenas bits, isto é '0' e '1' literalmente.\n\n## Principais Recursos\n\nfeature/Recorder:\n\n- Este módulo é responsável por estruturar e filtrar os bits a serem processados e no fim, gerar um arquivo de audio WAV contendo uma frequência com manipulações no volume. O volume da frequência só registram 3 valores, são eles representados por 0, 1, DIVISOR. O divisor é o elemento que permite entender a pausa entre cada bit tornando possível entender que após cada pausa existe um novo bit de informação. Essa ideia foi baseada na forma que CD's digitais funcionam.\n\nfeature/Reader:\n\n- O Reader tem a função de ler o arquivo de audio WAV e extrair as informações da frequência/volume e converter cada onda em bit no valor de 0 ou 1. Os divisores são ignorados restando apenas os bits 0 e 1 no fim.\n\nÉ possível solicitar a informação do Header do arquivo gerado. Para isso você deve chamar o método `loadFileHeaderTypeId(\u003cdiretorio para arquivo\u003e)`, então, o Reader vai ler a posição definida para guardar os bits que correspondem ao `typeId` do arquivo. O dado do `typeId` retornado será do tipo numérico (number) e você pode usar o módulo `loadersTypesId.ts` para checar qual Loader deve ser usado para interpretar os bits.\n\nFoi implementado um recurso que força a correção na leitura dos bits. Hora ou outra foi notado em alguns arquivos gerados que alguns bits defeituosos apareceram na sequencia de bits lidos. Agora existe um algorítmo que analisa os bits e os corrige.\n\nfeature/Loaders:\n\n- São responsáveis por definir o tipo de leitor para cada arquivo. Cada um deve ter uma Header contendo informações de como interpretar os bits do arquivo a ser lido/escrito. O dado mais básico obrigatório é o parametro `typeId` que consome um total de 1 byte (8 bits). Assim sendo, o valor máximo em decimal para o typeId é de 255. É possível informar mais dados na header usando o segundo parametro no construtor da Header `additionalParams` passando um array de dados, neste caso, a ordem importa uma vez que a ordem de escrita também será a ordem esperada de leitura.\n\nfeature/loaders/utils/Header:\n\n- Header deve ser usado para construir o cabeçalho de cada Loader obrigatoriamente.\n\n/loadersTypesId\n\n- O tipo de cada loader está guardado no arquivo `loadersTypesId.ts`. Todos os tipos devem ser guardados neste módulo no intuito de padronizar o projeto. No entanto, é possível apenas gerar arquivos de bits sem cabeçalho. Quando isso acontece, é necessário que o leitor anônimo saiba interpretar os bits.\n\n## Loaders ( Usados para interpretar os bits em informação humana como texto, número, imagem, etc )\n\nCada Loade deve ter obrigatoriamente Um Header e dois métodos (encode e decode). Encode exige que a saída seja do tipo `EncodeOutput`. Após receber uma instancia do `EncodeOutput` basta você chamar a propriedade `bits`. Exemplo: `myEncodedOutput.bits`.\n\n- DecimalNumber: O primeiro tipo de arquivo suportado pelo programa criado. Pode salvar números decimais convertidos em bits dentro de uma frequência de arquivo de audio WAV. Você pode ver como usar através dos testes na pasta 'tests/loaders/DecimalNumber.test.ts'.\n\n- Alphanumeric: Este loader pode ser usado para codificar e decodificar informações suportando uma grande maioria das caracteres usadas no mundo. Na verdade suporta qualquer um até os testes atuais baseado na arquitetura atual deste loader. Os bits de cada caractere são armazenados usando a maior quantidade de bits necessarios do maior caractere. Por exemplo, se um caractere X gasta 10 bits (em binario), todos os outros precisam usar também este espaço, mesmo que não necessite. Sempre o maior valor de bits do maior caractere será usado como padrão para as menores. Este loader já faz este tratamento.\n\n## Helpers\n\nfeature/DecodedChunks:\n\n- Este é um recurso que é usado para armazenar pedaço por pedaço de um arquivo e retornar os dados de bits.\n\nfeature/BitToneBuffer:\n\n- Usado para tratar pedaços de buffer com o recurso de concatenação. Exemplo: BitToneBuffer.concat(list: Array\u003cBuffer\u003e);\n\n## Como usar\n\nO projeto tem diversos testes. Por hora, use-os como documentação. Esse conteúdo vai ser melhorado posteriormente.\n\n## Roadmap\n\n- Capacidade de ler bites em tempo real. Enquanto o audio está sendo tocado. (https://www.npmjs.com/package/naudiodon)\n- Recorder deve passar um Loader type no segundo parametro? Ou continuar pedindo apenas o Header type?\n- Capacidade para ler outros formatos de arquivos de áudio e extrair os bits, exemplo: mp3, ogg, etc.\n- Usar [TypeDoc](https://typedoc.org/) para gerar documentação?\n- Trocar os recursos deprecados do Buffer pelos recomendados e mais seguros.\n- Trocar o deprecatedBuffer.ts pelo mais novo e não deprecado;\n- Criar PR contendo os arquivos d.ts para wav-encoder e wav-decoder?;\n- Melhorar os loaders de Bitmap para gerar bmp usando apenas os bits de cores e nao utilizar os nulos. Todos eles estão gerando arquivos com o mesmo tamanho mesmo que eles tenham menos dados de cor.\n- Testar arquivos com 384000Hz [o mesmo do disco da voyager] ao invéz de 44100Hz (amostras por segundo);\n- Estudar como gerar a lib só quando necessário (porque o código vai para o repo sem a lib contendo apenas o TypeScript).\n- Configurar o binário (relacionado ao tópico acima).\n- Escolher a licença apropriada.\n- Postar os dados do algorítmo que está na cardeneta (o mesmo que já está sendo usado no projeto mas mais detalhado).\n- Refazer o desenho da capa do disco com as informações para ler o disco:\n\n  - Sobre o hidrogêncio e seu comprimento: https://en.wikipedia.org/wiki/Hydrogen_line\n\n- Sample rate vai de -1 a 1, ou seja, temos um total de 2 de cumprimento, para se achar o \"SampleByte\" basta fazer o cálculo\n  2 / 255 (valor total de 1 byte em decimal) que vai dar 0.0078431373;\n\n- Para guardar os valores basta fazer o seguinte cálculo:\n  Ex1: 00011110 (binário) =\u003e 30 (decimal) =\u003e (SampleByte \\* 30) - 1 = -0.764705881 (final SampleRate position); Onde\n  \"-1\" é o ajuste da posição na largura do sampleRate;\n\n- Para fazer o processo contrário (ler o dado), fazer o seguinte cálculo:\n  Ex1: (-0.764705881 + 1) / SampleByte =\u003e 30 (decimal) =\u003e 0001110 (binário); Onde o primeiro valor é o sampleRate lido\n  do arquivo de audio e o \"+1\" é o ajuste que define a posição dentro do limite de largura de um sampleRate;\n\n- Criar o metodo de ler e escrever em Stereo (guardar os bits de forma intercalada):\n  dado 01101100\n  processar:\n  ch1:0110\n  ch2:1010\n\n- Os decoders de bitmap estão gerando arquivos\n\n## Melhoria\n\nEnquanto trabalhando na ferramenta desktop, percebi que é possível ler os bytes do arquivo do buffer bruto. Ou seja, ler o arquivo .wav bruto no formato Uint8Array (que já vai converter os sampleRates para decimal entre 0 - 255) pular os bits do Header WAV (que vai do 0 ao 43) e a partir daí, já é possível ler as informações dos Loaders. Exemplo: indice 44 vai ser o TypeId e dai por diante.\n\nPara obter a onda sonóra, basta converter Uint8Array para Float32Array.\n\nLink sobre conversão: https://stackoverflow.com/questions/34669537/javascript-uint8array-to-float32array\n\nDesta forma, vai ser poupado processo que tranforma os sampleRates em decimal. (Ver arquivo getBitsFromBuffer.ts)\n\nAqui a solução já desenvolvida:\n\n```ts\n// ---------- Modo lendo os bytes do sampleRates direto com Uint8Array (retorna decimal) ---------\n// Não está sendo lido a informação de quantos canais, etc. Para saber disso, deve-se ler\n// o ponteiro certo na HEADER do arquivo WAV. Aqui esta sendo usado o modo default\n// do programa que é 1 canal com um sample rate de 44100\nconst buffer: Buffer; // Buffer do arquivo de audio .wav codificado bruto.\nconst decimalSampleData: Uint8Array = Uint8Array.from(buffer.slice(44)); // WAV header tem 44 bytes\n// basta agora converter os valores de `decimalSampleData` para binario no Reader do programa.\n\n// Se for necessário reproduzir o conteúdo, deve converter os valores para Float32Array que vai definir\n// o comprimento do sampleRate (modelo usado para audio):\nconst floatSampleData: Float32Array = new Float32Array(\n  decimalSampleData.length\n);\ndecimalSampleData.forEach((uint8Value, index) =\u003e {\n  floatSampleData[index] = (uint8Value - 128) / 128.0;\n});\n\n// Esse `floatSampleData` pode ser facilmente tocado usando este exemplo:\n// https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer\n```\n\nCom essa solução, o moduleo `wav-decoder` pode ser descartado (a não ser que seja requerido ler o Wav Header). Mas creio que não.\n\n**ATENÇÃO: O inverso do processo acima deve ser feito também para gravar os dados usando o Recorder.**\n\n**ATENÇÃO 2:** O core precisará sofrer uma re-estruturação para não fazer conversões para binário representacional. Atualmente estou convertendo os valores para strings de 0s e 1s porque o processo de Gravar e Ler antigo, quando se usava tons, rigistrava o tom de acordo com o valor 0, 1 ou DIVISOR. Este processo de tons foi removido, assim sendo, o processo de se ter o binários em string também deve ser removido. Deve-se guardar os valores diretamente no formato Float32Array de cada Loader e este ser entregue ao Recorder posteriormente. O cálculo do SAMPLE BYTE vai servir apenas como referência e escrita de bytes (já que a fórmula para transformar Uint8 em Float32 está causando defeito de entregar o valor - 1)\n\n## Video Loader\n\n44100 / 4 frames = 11025 pixels; (8 bits por pixel ou 1 byte por pixel)\nOu seja, 1 segundo suporta 4 frames contendo 11025 pixels.\n1a Resolução possível: 106x104 (Muito quadrada) = 11024 pixels\n2a Resolução possível: 120x92 (Mais retangular) = 11040 pixel\n106 - largura\n104 - altura\n\nPara imagens geradas com 4 bits por pixel, a resolução máxima disponível é\n187x118 para gerar 4 frames por segundo.\n\n## Util\n\n- Gerar BMP: https://online-converting.com/image/convert2bmp/#\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwpdas%2Fdigital-voyager-image-sound-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwpdas%2Fdigital-voyager-image-sound-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwpdas%2Fdigital-voyager-image-sound-core/lists"}