Создание простого музыкального плеера на C с использованием библиотеки miniaudio

В этой статье мы создадим простой консольный музыкальный плеер на языке программирования C. Плеер будет поддерживать воспроизведение файлов форматов .wav, .mp3 и .flac, а также базовое управление (воспроизведение, пауза, переключение треков и регулировка громкости). Мы будем использовать библиотеку miniaudio для работы со звуком.

Шаг 1: Подготовка системы

Перед началом работы убедитесь, что ваша система готова к разработке. Мы будем использовать Arch Linux, но инструкции можно адаптировать для других дистрибутивов.

Установка необходимых зависимостей

  1. Обновите систему: sudo pacman -Syu
  2. Установите компилятор GCC и инструменты разработки: sudo pacman -S gcc make
  3. Создайте каталог для проекта: mkdir ~/music_playercd ~/music_player

Шаг 2: Скачивание и настройка библиотеки miniaudio

Библиотека miniaudio — это легковесная библиотека для работы со звуком. Она не требует сложной установки, так как распространяется в виде одного заголовочного файла.

  1. Скачайте miniaudio: Перейдите на официальный репозиторий библиотеки: https://github.com/mackron/miniaudio wget https://raw.githubusercontent.com/mackron/miniaudio/master/miniaudio.h
  2. Поместите miniaudio.h в каталог проекта: Убедитесь, что файл находится в том же каталоге, что и ваш исходный код.

Шаг 3: Написание кода

Создайте файл player.c и скопируйте в него следующий код:

#include "miniaudio.h"
#include 
#include 
#include   // Для strcmp, strrchr, strlen, strcpy
#include   // Для opendir, readdir, closedir
#include  // Для stat

#define MAX_TRACKS 1000

typedef struct {
    char* tracks[MAX_TRACKS];
    int track_count;
    int current_track;
    ma_engine engine;
} MusicPlayer;

// Реализация strdup
char* my_strdup(const char* str) {
    if (str == NULL) return NULL;
    size_t len = strlen(str) + 1; // Длина строки + нулевой символ
    char* copy = malloc(len);     // Выделяем память
    if (copy == NULL) return NULL;
    strcpy(copy, str); // Копируем строку
    return copy;
}

void load_music_files_recursive(const char* directory, MusicPlayer* player) {
    DIR* dir = opendir(directory);
    if (!dir) {
        perror("opendir");
        return;
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL) {
        // Пропускаем специальные директории "." и ".."
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        char full_path[1024];
        snprintf(full_path, sizeof(full_path), "%s/%s", directory, entry->d_name);

        struct stat st;
        if (stat(full_path, &st) == -1) {
            perror("stat");
            continue;
        }

        if (S_ISDIR(st.st_mode)) {
            // Это директория — обходим её рекурсивно
            load_music_files_recursive(full_path, player);
        } else if (S_ISREG(st.st_mode)) {
            // Это файл — проверяем расширение
            const char* ext = strrchr(entry->d_name, '.');
            if (ext && (strcmp(ext, ".wav") == 0 || strcmp(ext, ".mp3") == 0 || strcmp(ext, ".flac") == 0)) {
                if (player->track_count < MAX_TRACKS) {
                    player->tracks[player->track_count] = my_strdup(full_path); // Копируем путь
                    player->track_count++;
                }
            }
        }
    }

    closedir(dir);
}

void load_music_files(const char* directory, MusicPlayer* player) {
    load_music_files_recursive(directory, player);

    if (player->track_count == 0) {
        printf("No music files found in %s or its subdirectories.\n", directory);
    } else {
        printf("Loaded %d tracks from %s and its subdirectories.\n", player->track_count, directory);
    }
}

void play_current_track(MusicPlayer* player) {
    if (player->current_track < 0 || player->current_track >= player->track_count) {
        printf("No tracks available.\n");
        return;
    }

    ma_engine_stop(&player->engine);
    ma_engine_uninit(&player->engine);

    ma_result result = ma_engine_init(NULL, &player->engine);
    if (result != MA_SUCCESS) {
        printf("Failed to initialize audio engine.\n");
        return;
    }

    printf("Playing: %s\n", player->tracks[player->current_track]);
    ma_engine_play_sound(&player->engine, player->tracks[player->current_track], NULL);
}

void cleanup_player(MusicPlayer* player) {
    for (int i = 0; i < player->track_count; i++) {
        free(player->tracks[i]); // Освобождаем память для каждого пути
    }
    ma_engine_uninit(&player->engine);
}

int main() {
    MusicPlayer player = {0};
    player.current_track = 0;

    // Загрузка файлов из каталога
    load_music_files("/home/gratz/Музыка", &player);
    if (player.track_count == 0) {
        return -1;
    }

    // Инициализация движка
    ma_result result = ma_engine_init(NULL, &player.engine);
    if (result != MA_SUCCESS) {
        printf("Failed to initialize audio engine.\n");
        return -1;
    }

    // Основной цикл
    char command[16];
    while (1) {
        printf("\nCommands: [play/pause] [next] [prev] [vol <0-1>] [quit]\n> ");
        scanf("%s", command);

        if (strcmp(command, "play") == 0 || strcmp(command, "pause") == 0) {
            ma_engine_stop(&player.engine); // Пауза
            play_current_track(&player);   // Возобновление
        } else if (strcmp(command, "next") == 0) {
            player.current_track = (player.current_track + 1) % player.track_count;
            play_current_track(&player);
        } else if (strcmp(command, "prev") == 0) {
            player.current_track = (player.current_track - 1 + player.track_count) % player.track_count;
            play_current_track(&player);
        } else if (strcmp(command, "vol") == 0) {
            float volume;
            scanf("%f", &volume);
            if (volume < 0.0f) volume = 0.0f;
            if (volume > 1.0f) volume = 1.0f;
            ma_engine_set_volume(&player.engine, volume);
            printf("Volume set to %.2f\n", volume);
        } else if (strcmp(command, "quit") == 0) {
            break;
        } else {
            printf("Unknown command.\n");
        }
    }

    cleanup_player(&player);
    return 0;
}

Шаг 4: Компиляция программы

  1. Скомпилируйте программу: gcc player.c -o player -lpthread -lm -std=c99
  2. Проверьте, что файл player создан: ls -l player

Шаг 5: Настройка каталога с музыкой

  1. Выберите каталог с музыкой: Убедитесь, что в каталоге /home/gratz/Музыка находятся файлы форматов .wav, .mp3 или .flac.
  2. Если каталог другой, измените путь в функции load_music_files: load_music_files("/путь/к/вашей/музыке", &player);

Шаг 6: Запуск программы

Запустите программу:

./player

Вы увидите список команд:

Commands: [play/pause] [next] [prev] [vol <0-1>] [quit]

Шаг 7: Использование

  • Воспроизведите трек командой play.
  • Переключите треки командами next и prev.
  • Измените громкость командой vol 0.5.
  • Завершите программу командой quit.

Заключение

Теперь вы знаете, как создать простой музыкальный плеер на языке C с использованием библиотеки miniaudio. Этот проект можно расширять и улучшать, добавляя новые функции, такие как графический интерфейс, поддержка плейлистов или интеграция с сетевыми сервисами. Удачи в разработке!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *