Share via


Como funciona o exemplo de eco

[O recurso associado a esta página, Reprodutor Multimídia do Windows SDK, é um recurso herdado. Foi substituído pelo MediaPlayer. O MediaPlayer foi otimizado para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use o MediaPlayer em vez de Reprodutor Multimídia do Windows SDK, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

O código cria o efeito de eco alocando um buffer grande o suficiente para conter exatamente a quantidade de dados de áudio que podem ser renderizados no período especificado pelo valor de tempo de atraso. O tamanho do buffer é calculado, em bytes, pela seguinte fórmula:

tamanho do buffer = tempo de atraso * taxa de exemplo / 1000 * alinhamento de bloco

O tempo de atraso é em milissegundos. A taxa de exemplo e os valores de alinhamento de bloco são fornecidos em uma estrutura WAVEFORMATEX. A taxa de exemplo está em exemplos por segundo; dividir por 1000 produz amostras por milissegundo. O alinhamento do bloco é igual ao produto do número de canais (1 para mono, 2 para estéreo) e o número de bits por amostra (8 ou 16) dividido por 8 (bits por byte).

Além da variável de ponteiro que aponta para o cabeçalho do buffer de atraso, o código cria um ponteiro móvel que percorre os dados no buffer em sincronização com o loop de processamento na função DoProcessOutput . Quando o ponteiro móvel atinge o final do buffer de atraso, ele volta para a cabeça do buffer. Um buffer usado dessa maneira é chamado de buffer circular.

Depois que o buffer de atraso existir e Reprodutor Multimídia do Windows tiver alocado um buffer de entrada para fornecer dados de áudio e um buffer de saída para receber dados de áudio processados, o processamento de eco continuará assim:

  1. Insira um loop que permita o processamento de cada exemplo de áudio no buffer de entrada.
  2. Recupere um exemplo do buffer de entrada. Em seguida, mova o ponteiro do buffer de entrada para a próxima amostra para se preparar para a próxima iteração de loop.
  3. Recupere um exemplo do buffer de atraso.
  4. Copie o exemplo do buffer de entrada para o mesmo local no buffer de atraso do qual o último exemplo de atraso foi recuperado.
  5. Mova o ponteiro do buffer de atraso para a próxima amostra. Se o ponteiro passar pela extremidade do buffer, mova-o para a cabeça do buffer.
  6. Combine o exemplo do buffer de entrada com o exemplo do buffer de atraso.
  7. Copie o resultado para o buffer de saída. Em seguida, mova o ponteiro do buffer de saída para a próxima unidade para se preparar para a próxima iteração de loop.
  8. Repita até que todos os exemplos sejam processados.

Quando um exemplo de entrada recuperado na etapa 2 é copiado para o buffer de atraso na etapa 4, ele permanece lá até que o ponteiro móvel percorra cada amostra no buffer de atraso e, por fim, retorne à mesma posição. Como o tamanho do buffer de atraso foi projetado para corresponder ao tempo de atraso, o tempo decorrido entre o exemplo que está sendo copiado para o buffer de atraso e o exemplo que está sendo recuperado mais uma vez é igual ao atraso especificado (mais qualquer latência introduzida pelo processamento real).

Quando um fluxo é iniciado, nenhum dado de atraso é gerado até que o tempo de atraso tenha decorrido. Portanto, é importante que o buffer de atraso inicialmente contenha silêncio. Se o buffer de atraso contiver dados aleatórios, o usuário ouvirá ruído em branco até que o plug-in gere dados de atraso suficientes para substituir todo o buffer de atraso.

Visão geral do exemplo de eco