Fale dígitos de 0 a 9 em voz alta

15

Inspirado por esta pergunta da electronics.SE , aqui está um desafio para você:

Escreva um programa ou sub-rotina que pegue uma sequência de dígitos decimais (0 a 9) e fale-os em voz alta, sem usar uma ferramenta de síntese de fala existente.

Entrada:

Você pode solicitar que os dígitos da entrada sejam fornecidos em qualquer formato razoável, por exemplo, como uma sequência de dígitos ASCII, uma matriz de números inteiros, um número codificado em BCD, etc. Se a sua solução for um programa executável, você poderá considerar a entrada como um parâmetro da linha de comandos, leia-o da entrada padrão ou obtenha-o de qualquer outra maneira razoável.

Seu programa deve ser capaz de falar pelo menos oito dígitos por chamada. Você pode assumir que o primeiro dígito não é zero, a menos que seja o único dígito.

Resultado:

Seu programa pode falar os números diretamente usando um dispositivo de áudio ou pode gerar um arquivo de som reproduzível. O arquivo de saída, se houver, pode estar em qualquer formato de áudio padrão ou pode consistir em dados de amostra brutos. Se você fornecer dados de amostra brutos, observe os parâmetros apropriados para a reprodução (taxa de amostragem, bits por amostra, endianness, assinado / não assinado, número de canais). Formatos suportados pelo aplay são preferidos.

Você é livre para decidir os detalhes de como os números serão falados, mas sua saída deve consistir em dígitos do idioma inglês falados de maneira compreensível para um falante típico de inglês e deve ser suficientemente claro para que o ouvinte possa transcrever com precisão um número aleatório falado de oito dígitos. Não, apenas apitar n vezes não conta. Não se esqueça de incluir pausas entre os dígitos.

Pontuação:

Aplicam-se as regras padrão pontuação de : Sua pontuação é o tamanho do seu código em bytes ou, se o seu código estiver escrito em texto Unicode, em caracteres Unicode. Menor pontuação ganha. Qualquer idioma vai.

Como a pergunta original sobre a eletrônica. E se tratava de programação incorporada, achei que seria apropriado lançar um osso para os autores usando linguagens de baixo nível: se a sua solução estiver escrita em uma linguagem compilada, você poderá contar a duração da arquivo executável compilado em bytes como sua pontuação. (Sim, .classo código de código pré-compilado, como um arquivo Java , também é bom.) Se você optar por fazer uso dessa opção, inclua uma cópia do executável compilado em sua resposta (por exemplo, como um hex dump) junto com seu código-fonte e a versão do compilador e as opções usadas para gerá-lo.

Uma menção honrosa , juntamente com uma recompensa de +50 representantes, será concedida à primeira resposta que também atenda aos critérios da pergunta original , ou seja, é capaz de rodar em um MCU incorporado com 4 kb de flash e 1 kb de SRAM.

Restrições:

Você não pode usar arquivos ou recursos de rede que não façam parte do ambiente de tempo de execução padrão do idioma escolhido, a menos que conte a duração desses arquivos ou recursos como parte de sua pontuação. (Isso é para não permitir, por exemplo, carregar amostras de áudio da Web.)

Você também não pode usar nenhuma ferramenta de síntese de fala, biblioteca ou compilação de dados de áudio preexistentes (a menos que você também conte o tamanho como parte da sua pontuação), mesmo que elas estejam incluídas no ambiente de tempo de execução padrão do idioma escolhido.

Ilmari Karonen
fonte
Ps. Posso postar uma solução própria depois, se conseguir produzir algo que pareça realmente compreensível. Não tenha vergonha de postar o seu próprio; neste ponto, qualquer resposta é uma boa resposta.
Ilmari Karonen
1
Podemos baixar um banco de dados de dígitos falados (e contar seu tamanho na partitura) ou temos que gravar nossa própria voz? Duvido que possa gerar amostras de fala por algoritmo.
quer
umm ... a seção "output" não especifica, devemos produzir amostras de fala. Podemos simplesmente emitir um bipe dez vezes?
quer
@ PeterTaylor: Se você contar o tamanho deles como parte da sua pontuação, tudo bem. Eu só estava preocupado que houvesse algum sistema por aí com amostras de áudio de dígitos enterrados em algum lugar do seu ambiente de tempo de execução padrão.
Ilmari Karonen
3
Como parece haver um fluxo constante de pessoas que não lêem a pergunta até o fim e publicam invólucros triviais em bibliotecas pesadas, talvez valha a pena editar para colocar ainda mais ênfase no aspecto "Faça você mesmo".
22613 Peter Peter

Respostas:

10

ruby - 3710 = código de 90 caracteres + dados de 3620 bytes

require'zlib'
$><<$*[0].chars.map{|x|Zlib::Inflate.inflate File.open(x).read}.join(?0*5e3)

input: um único argumento de linha de comando, o número a ser lido

saída: dados de som brutos, PCM 8bit / 8kHz

Isso pode ler qualquer sequência de entrada, desde que

  • ele contém apenas caracteres com nomes de arquivo válidos. por apenas quatro caracteres, você pode ampliar esse conjunto para todos os caracteres.
  • você tem os arquivos necessários.
  • por que oh você espaço dee oh no apóstrofo tee space em i no dee tee tee aitch i es period

5e3codifica a pausa entre duas palavras. Aqui, 5 amostras = 0,6s. Ajuste conforme desejado.

Agora, a parte mais complicada é obter os arquivos de amostra em 4K e ainda poder descompactá-los facilmente e com qualidade suficiente. Aqui está como eu os peguei:

  • Pegue um mecanismo de conversão de texto em fala capaz de produzir arquivos de som. A Wikipedia possui um .
  • Alimente-o com um texto contendo todos os dígitos, idealmente próximos. Eu usei http://en.wikipedia.org/wiki/Base_13
  • Downsample.
  • Recorte cada parte em um editor de som .
  • Salve como um arquivo bruto.
  • Dizime cada amostra (descarte os bits de baixa ordem).
  • Desinflar.

Agora, é preciso escolher uma taxa de amostragem e um valor de dizimação. Demais, e o som não será compreensível. Muito pouco e você não se encaixa. Eu me conformei com 8kHz / 3b. Lá estão eles: https://github.com/honnza/drops/raw/master/digits.zip

  • 8KHz * 4b / amostra e qualidade superior - muito grande
  • 8KHz * 3b / amostra - baixa qualidade, mas cabe em 4K
  • 8KHz * 2b / amostra - kch kchhhhhhhhh [não compreensível]
  • 2KHz * 8b / amostra - grande demais
  • 2KHz * 3b / amostra - kch kchhhhhhhhh
  • 1KHz * 8b / amostra - kch kchhhhhhhhh

Aqui está o script de dizimação:

require'zlib'
Dir.glob "*.raw" do |fname|
  File.open fname[/\d/], "wb" do |out|
    File.open fname do |input|
      bytes = input.bytes.to_a
      bytes.map! {|x|x&0xE0}
      dfl = Zlib::Deflate.deflate(bytes.pack("C*"),9)
      dfl.each_byte do |byte|
        out.print byte.chr
      end
      puts "done #{fname}: #{dfl.size}"
    end
  end
end

Quanto ao desafio original: existem 476 bytes de espaço para o código e a tabela de arquivos. Isso pode ser um pouco demais, dependendo do tamanho que podemos obter com uma biblioteca DEFLATE. Se necessário, podemos cortar alguns cantos aqui e ali cortando as amostras de áudio um pouco mais agressivamente. [fo:r]ou [o:]realmente não importa, mas salva bytes. Fui um pouco benevolente ao cortar os números. Além disso, um esquema de dizimação diferente ou o sacrifício de alguma dizimação por downsampling pode ajudar - vou brincar com isso mais tarde. Além disso, soltar os cabeçalhos DEFLATE pode economizar uma pequena quantidade de espaço.

Concatenar amostras de som é bastante fácil, mas o 4K é um pouco apertado. Se você não está limitado pelo espaço de 4k, sugiro menos dizimação. Na verdade, 4 bits por amostra se saem muito bem e são apenas um pouco maiores.

John Dvorak
fonte
+1, nada mal. A clareza é bastante marginal: tentei transcrever alguns números aleatórios e obtive uma taxa de sucesso de 70%. (Eu esperava algo mais próximo de 99%.) Ainda estou em dúvida sobre a menção honrosa: embora você tenha argumentado muito bem que o 4K pode ser atingido dessa maneira, você não realmente demonstrou isso. Mesmo se você abandonou o ruby ​​para C (o que parece fácil de fazer; eu estaria disposto a participar dessa fé), você poderia realmente colocar um decodificador DEFLATE no espaço restante do flash? Além disso, como observei, a qualidade do som é muito ruim.
Ilmari Karonen
Ps. Algumas dicas para melhorar a compactação: você pode compactar todas as amostras em um comprimento fixo com bytes nulos (que devem ser compactados bem) e concatená-las em um arquivo compactado, depois descompactá-las e cortá-las. Além disso, o truque KZIP desta resposta pode fornecer uma melhor compactação DEFLATE. Por fim, tente editar o arquivo de som combinado para substituir fonemas equivalentes por cópias exatas.
Ilmari Karonen
bem, as amostras de som originais não eram exatamente compreensíveis também na IMO - a amostragem reduzida causou pouco dano a isso. A menor biblioteca DEFLATE que eu conheço - a primeira vinculada pela wikipeda - pesa cerca de 500b. Francamente, você quer que eu carregue o inflador para esse dispositivo específico? Talvez eu consiga, na verdade, mas nunca codifiquei o ARM antes.
John Dvorak
Estou bastante surpreso com a taxa de sucesso de 70% - achei os números fáceis de entender. Quais dígitos você mais confundiu?
John Dvorak
Portá-la para um Cortex M0 é provavelmente um pouco demais para pedir (embora se você pudesse fazer isso, que seria incrível!), Mas eu acho que um binário stand-alone (arquivos de dados +, se houver) encaixando sob 4k pareceria uma demonstração razoável. (Não é necessário vincular estaticamente na libc a E / S de arquivo, pois você não precisaria disso em um dispositivo incorporado, mas o código DEFLATE certamente deve ser contado.) Basicamente, algo que você pode postar como resposta à pergunta original em electronics.SE e diga com confiança "se você compilar isso para o seu dispositivo, aposto que ele será adequado".
Ilmari Karonen