Abaixo está minha solução para a Semana 4 do CS50: Volume . O problema que eu estava tentando resolver era ler um arquivo .wav e alterar seu volume com base em um argumento de linha de comando 'factor'.
Problema:
Quando eu estava testando este código, usei inicialmente
fread(header, HEADER_SIZE, 1, input);
Meu código seria compilado sem erros e um arquivo de saída seria produzido para o seguinte:
./volume input.wav output.wav 1.0
Mas um arquivo de saída corrompido seria produzido se eu alterasse o fator de volume para qualquer valor diferente de 1,0.
// Modifies the volume of an audio file
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
// Number of bytes in .wav header
const int HEADER_SIZE = 44;
void copy_header(FILE *input, FILE *output);
void copy_samples(FILE *input, FILE *output, float factor);
int main(int argc, char *argv[])
{
// Check command-line arguments
if (argc != 4)
{
printf("Usage: ./volume input.wav output.wav factor\n");
return 1;
}
// Open files and determine scaling factor
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
printf("Could not open file.\n");
return 1;
}
FILE *output = fopen(argv[2], "w");
if (output == NULL)
{
printf("Could not open file.\n");
return 1;
}
float factor = atof(argv[3]);
copy_header(input, output);
copy_samples(input, output, factor);
// Close files
fclose(input);
fclose(output);
}
void copy_header(FILE *input, FILE *output)
{
uint8_t header[HEADER_SIZE];
fread(header, sizeof(HEADER_SIZE), 1, input);
fwrite(header, sizeof(HEADER_SIZE), 1, output);
printf("header: %s; header_size: %lu; HEADER_s: %lu\n", header, sizeof(header), sizeof(HEADER_SIZE));
}
void copy_samples(FILE *input, FILE *output, float factor)
{
int16_t buffer;
while (fread(&buffer, sizeof(int16_t), 1, input) != 0)
{
buffer = buffer * factor;
fwrite(&buffer, sizeof(int16_t), 1, output);
}
}
Depois de muita pesquisa, descobri que a saída para:
printf("header: %s; header_size: %lu; HEADER_s: %lu\n", header, sizeof(header), sizeof(HEADER_SIZE));
Seria:
header: RIFFDb; header_size: 44; HEADER_s: 4
Por que o valor de sizeof(HEADER_SIZE) mudou para 4? Estou perdendo completamente alguma coisa aqui? Abordei esse problema corretamente?
Corrigi o erro no meu código usando:
fread(header, sizeof(header), 1, input);
Mas eu quero saber por que e como eu estraguei esse código. Obrigado antecipadamente!
Ao olhar para estas linhas:
Você parece ter a impressão de que, após a declaração de
header
, o tamanho deHEADER_SIZE
agora está vinculado ao tamanho deheader
. Não é o caso.O
sizeof
operador avalia o tamanho em bytes do seu operando. No caso desizeof(HEADER_SIZE)
o operando é a variávelHEADER_SIZE
(ou mais precisamente, a variável entre parênteses) cujo tipo éint
. Isso avalia 4 porque anint
ocupa 4 bytes no seu sistema.Isso causou um problema no seu código, pois ele leu apenas 4 bytes em vez de 44, como você pretendia.
Isso funciona:
Porque
sizeof(header)
fornece o tamanho em bytes doheader
array, que é 44.Isso também funcionaria:
Como seria passar 44 como o número de bytes a serem lidos.