ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CS50 Week4: Lab4, Volume
    Programming/CS50 2023. 7. 10. 18:04

    하버드 CS50 강의 4주차 Lab 과제 Volume 의 풀이 과정을 다룹니다.
    C언어로 wav 파일을 읽고 조작하는 문제입니다.

    Intro

    문제 링크에서 자세한 내용을 확인할 수 있습니다.

    주어진 wav 파일의 볼륨을 높이는 문제

    $ ./volume INPUT.wav OUTPUT.wav 2.0

    Template

    템플릿이 주어져서 필요한 부분만 채우면 된다.

    // 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;
    
    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]);
    
        // TODO: Copy header from input file to output file
    
        // TODO: Read samples from input file and write updated data to output file
    
        // Close files
        fclose(input);
        fclose(output);
    }

    Code

    파일을 읽고 sample이 있는 버퍼에 factor를 곱해주면 된다.

    uint8_t header[HEADER_SIZE];
    
    fread(header, HEADER_SIZE, 1, input);
    fwrite(header, HEADER_SIZE, 1, output);
    
    int16_t buffer;
    while (fread(&buffer, sizeof(int16_t), 1, input) == 1)
    {
        buffer *= factor;
        fwrite(&buffer, sizeof(int16_t), 1, output);
    }

    Issue: 윈도우와 리눅스의 개행문자 차이

    전에도 한번 언급했지만, 나는 CS50에서 제공하는 웹 기반 VSCODE 환경을 사용하지 않고 있다.

    이유는

    1. 실행하는 데 시간이 걸리고
    2. 어짜피 나중가면 코딩은 내 노트북에서 할 테니까 조금 친해지는 겸...

    그래서 가끔 과제 채점 할 때만 가끔씩 Check50로 확인만 하곤 하는데,
    노트북은 윈도우고, CS50 강의 환경은 리눅스 기반이라 과제 수행에 이따금씩 문제가 발생한다.

    무튼 이번에는 입출력 라이브러리에서 파일을 읽는 데 이슈가 생겼다.
    두 운영체제 간 개행 문자(New-line Character)가 차이가 있어서 발생한 일이다.

    먼저 fopen()은 기본으로 text stream을 상정하고 파일을 읽고, text stream은 개행 문자를 기준으로 각 줄을 구별한다.

    한편 리눅스 기반 시스템의 개행 문자는\n 이고 윈도우는 \r\n라서, C 에서 텍스트 스트림을 읽을 때는 윈도우의 \r\n을 자동으로 \n으로 바꿔서 읽어준다

    예제에서 다룬 wav 포멧은 텍스트가 아닌 바이너리 파일이다.

    리눅스에서는 개행문자와 관련된 특수한 처리가 필요하지 않기 때문에 텍스트로 읽거나 바이너리로 읽거나 별 차이가 없다.

    한편 윈도우에서는 의도하지 않은 파일 변화가 생길 수 있기 때문에 파일을 읽을 때 어떻게 읽을 것인지 명시를 해 줘야 한다.

    따라서 예제 코드의 fopen()의 파일 접근 모드를 rb, wb로 변경해야 한다.....

    참고자료

    https://en.cppreference.com/w/cpp/io/c/fopen
    https://en.cppreference.com/w/c/io/FILE
    https://modoocode.com/34

    댓글