CS50-MCZ

Uma introdução aos empreendimentos intelectuais da Ciência da Computação e da arte da programação.


Reverse


Implemente um programa que inverta um arquivo WAV, conforme abaixo.

./reverse input.wav output.wav
    

Contexto

Na música "Fire on High" da Electric Light Orchestra, há algo um pouco estranho nos primeiros minutos da música. Se você ouvir, parece quase como se o áudio estivesse tocando ao contrário. Como acontece, se você reproduzir a seção inicial da música ao contrário, você ouvirá o seguinte:

"The music is reversible. Time is not. Turn back, turn back!"

Assustador, não é? Essa é uma técnica chamada "backmasking", ou seja, esconder mensagens na música que só podem ser ouvidas quando a música é tocada ao contrário. Muitos artistas usaram (ou foram suspeitos de usar) essa técnica em suas músicas. Para poder fazer nossa própria investigação sobre o backmasking, pedimos que você escreva um programa que possa inverter arquivos WAV para nós!

Ao contrário de arquivos de áudio MP3, os arquivos WAV não são comprimidos. Isso torna os arquivos muito mais fáceis de editar e manipular, o que é útil para a tarefa em questão. Para aprender um pouco mais sobre arquivos WAV, precisamos dar uma olhada mais de perto no formato de arquivo WAV.

Começando

Acesse o code.cs50.io, clique na sua janela do terminal e execute cd sozinho. Você deve encontrar que o prompt da sua janela do terminal se assemelha ao abaixo:

$

Em seguida, execute

wget https://cdn.cs50.net/2022/fall/psets/4/reverse.zip

Para baixar um arquivo ZIP chamado reverse.zip em seu codespace.

Em seguida, execute

unzip reverse.zip

para criar uma pasta chamada reverse. Você não precisa mais do arquivo ZIP, então pode executar

rm reverse.zip

e responda com "y" seguido de Enter no prompt para remover o arquivo ZIP que você baixou.

Agora digite

cd reverse

seguido de Enter para mover-se para (ou seja, abrir) esse diretório. Seu prompt agora deve se parecer com o abaixo.

reverse/ $

Se tudo ocorreu com sucesso, você deve executar:

ls

e veja um arquivo chamado reverse.c e 'card.raw'. Executando code reverse.c deverá abrir o arquivo onde você irá digitar o seu código para este conjunto de problemas. Se não, refaça seus passos e veja se consegue determinar onde errou!

O formato de arquivo WAV

Observe que, na imagem abaixo, um arquivo WAV é dividido em três blocos. Cada bloco contém alguns blocos de dados.

O primeiro bloco contém informações sobre o tipo de arquivo. Em particular, observe como o bloco "Formato do arquivo" no primeiro bloco soletra 'W''A''V''E' nos bytes 8-11, para indicar que o arquivo é um arquivo WAV.

O segundo bloco contém informações sobre os próximos dados de áudio, incluindo quantos "canais" de áudio estão presentes e quantos bits há em cada "amostra" de áudio. Arquivos de áudio têm 1 canal quando são "monofônicos": se você estiver usando fones de ouvido, ouvirá o mesmo áudio em sua orelha esquerda e direita. Arquivos de áudio têm 2 canais quando são "estereofônicos": usando fones de ouvido, você ouvirá áudios ligeiramente diferentes em sua orelha esquerda e direita, criando uma sensação de espaço. As amostras são os blocos individuais de bits que compõem o áudio que você ouve. Com mais bits por amostra, um arquivo de áudio pode ter maior clareza (ao custo de mais memória usada!).

Finalmente, o terceiro bloco contém os dados de áudio em si - as amostras mencionadas acima.

Tudo antes dos dados de áudio é considerado parte do "cabeçalho" WAV. Lembre-se de que um cabeçalho de arquivo é simplesmente alguns metadados sobre o arquivo. Neste caso, o cabeçalho tem 44 bytes de comprimento.

Cabeçalho WAV

Uma explicação mais técnica dos cabeçalhos WAV pode ser encontrada aqui, que é a fonte pela qual esta imagem foi inspirada. Observe que incluímos um arquivo, wav.h, que implementa todos esses detalhes para você em uma struct chamada WAVHEADER.

Especificação

Vamos escrever um programa chamado reverse que nos permita reverter um arquivo WAV fornecido pelo usuário e criar um novo arquivo WAV que contenha o áudio resultante revertido. Para simplificar, limitaremos os arquivos que lidamos ao formato WAV. No momento em que o usuário executa o programa, ele deve fornecer, usando dois argumentos de linha de comando, o nome do arquivo de entrada a ser lido e revertido e o nome do arquivo de saída em que eles gostariam de salvar o áudio resultante. Um programa executado com sucesso não deve produzir nenhum texto e deve criar um arquivo WAV com o nome especificado pelo usuário que reproduza o áudio do arquivo WAV de entrada invertido. Por exemplo:

$ ./reverse input.wav output.wav

No arquivo reverse.c, você notará que algumas bibliotecas úteis foram incluídas, bem como um arquivo de cabeçalho, wav.h. Provavelmente você vai achar isso útil ao implementar seu programa. Deixamos oito TODOs e duas funções auxiliares para você preencher e recomendamos que você os aborde em ordem de 1 a 8.

Este pode ser um bom lugar para parar e testar se o seu programa se comporta conforme o esperado. Se implementado corretamente, o seu programa deve abrir um novo arquivo quando executado com os argumentos corretos da linha de comando.

Se em algum momento você achar necessário excluir um arquivo, execute o seguinte comando no diretório de trabalho atual.

$ rm file_name.wav

Se você preferir não ser solicitado a confirmar cada exclusão, execute o comando abaixo em vez disso.

$ rm -f file_name.wav

Apenas tenha cuidado com o interruptor -f, pois ele "força" a exclusão sem solicitar confirmação.

Uso

Aqui estão alguns exemplos de como o programa deve funcionar. Por exemplo, se o usuário omitir um dos argumentos da linha de comando:

$ ./reverse input.wav
Usage: ./reverse input.wav output.wav
  

Ou se o usuário omitir ambos os argumentos da linha de comando:

$ ./reverse
Usage: ./reverse input.wav output.wav
    

Aqui está como o programa deve funcionar se o usuário fornecer um arquivo de entrada que não seja um arquivo WAV real:

$ ./reverse image.jpg output.wav
Input is not a WAV file.
      

Você pode assumir que o usuário insere um nome de arquivo de saída válido, como output.wav.

Um programa executado com sucesso não deve imprimir nenhum texto e deve criar um arquivo WAV com o nome especificado pelo usuário que reproduza o áudio do arquivo WAV de entrada ao contrário. Por exemplo:

$ ./reverse input.wav output.wav

Testando

Execute o abaixo para avaliar a correção do seu código usando check50. Mas certifique-se de compilar e testar também!

check50 cs50/problems/2023/x/reverse

Execute o código abaixo para avaliar o estilo do seu código usando style50.

style50 reverse.c

Como Submeter

No seu terminal, execute o comando abaixo para submeter o seu trabalho.

submit50 cs50/problems/2023/x/reverse