0

Endcoding nhạc sử dụng LAME MP3

I. LAME MP3 là gì

LAME là một trong hầu hết các codec âm thanh lossy phổ biến. Nó cho phép bạn nén các file audio sang định dạng MPEG-1 / MPEG-2 định dạng, được lưu trữ trong các tập tin MP3. LAME cung cấp một loạt các bitrate nén: 8-320 kb / s và lấy mẫu giá: 8-48 kHz. Do sự phổ biến codec này, người ta có thể quan tâm trong việc thực hiện MP3 ở dạng bản địa thông qua các bản giao diện Java cho một ứng dụng Android. Bài viết này sẽ đi qua quá trình biên soạn bản của thư viện LAME, thực hiện một wrapper đơn giản cho các bộ mã hóa và tạo ra một ứng dụng Android mẫu mà thu âm thanh và mã hóa nó.

*Lossy nghĩa là dữ liệu nhạc đã bị các thuật toán lược bỏ đi để làm cho file nhạc nhẹ hơn và âm thanh cũng vì thế mà bị thay đổi khá nhiều.

  • Định dạng nhạc lossy phổ biến nhất là đuôi MP3, AAC và OGG.

  • Các thuật toán sẽ tính toán để lược bỏ các phần âm thanh trong file nhạc ít được nghe nhất. Tùy theo bit rate của file nhạc mà âm thanh sẽ bị cắt hết từ các tần số 16kHz-20kHz. Tuy nhiên, ngày nay đã có các thuật toán nén mà sau khi xử lý file nhạc vẫn có thể thấy quang phổ của file nhạc vẫn gần giống như ban đầu, vẫn có các âm thanh có tần số cao hơn 20kHz, các thuật toán này chỉ lược bỏ từng phần nhỏ trong file nhạc chứ không cắt hết toàn bộ dữ liệu.

  • Kích cỡ các file nhạc lossy sẽ chỉ còn bẳng khoảng 1/10 cho đến 1/3 file nhạc ban đầu.

  • Sau khi giải nén, các dữ liệu nhạc đã bị bỏ đi vẫn sẽ mất.

  • Tỉ lệ bit cao nhất cho các file nhạc lossy thường là khoảng 320 kbps và 500kbps, và tỉ lệ bit thông thường là 128 kbps, 256kbps và 192 kbps, thấp hơn rất nhiều so với tỉ lệ bit của file nhạc lossless phía trên (1411 kbps).

  • Nói đến lossy không thể không nhắc đến các file nhạc từ iTunes của Apple. Các file nhạc này có mã là AAC và có định dạng m4a, bit rate file nhạc ở 256kbps. Được Apple nén từ các file nhạc chuyển trực tiếp từ các công ty sản xuất âm nhạc, với các thiết bị tốt nhất, cùng với thuật toán nén tuyệt vời vốn có. Nên AAC iTunes là một trong những định dạng lossy tốt nhất hiện nay. Có quang phổ đẹp tương đương với lossless, chất lượng âm thanh cao hơn với MP3 320kbps.

II. Cấu hình môi trường

  • Để sử dụng JNI trong Android, Android NDK là cần thiết. Nó là một tập hợp các công cụ sử dụng để xây dựng các thành phần ứng dụng Android trong mã nguồn gốc. Nó có thể được tải về từ trang web của nhà phát triển Android:
  • Thư viện LAME có thể được tải về từ các trang web sau đây:

http://lame.sourceforge.net/download.php

Khi tải về xong, một phiên bản ban đầu (không có một wrapper chức năng) của các thư viện chia sẻ được tạo ra có thể được xây dựng. Để làm như vậy, nó là cần thiết để tạo ra một thư mục gọi là JNI trong thư mục gốc của dự án. Sau đó sao chép các libmp3lame thư mục từ các kho lưu trữ tải về vào một tạo. Nó là cần thiết để sao chép tất cả *. c và *. h file, vì vậy tất cả những người khác có thể được bỏ qua. Các tập tin tiêu đề thư viện chính tên què h cũng là cần thiết. Nó được đặt trong bao gồm thư mục trong kho lưu trữ được tải về. Copy nó như là phần còn lại của tập tin vào libmp3lame thư mục.

Một số chế phẩm phải được vạch ra. Kể từ khi các phương pháp biên soạn tiêu chuẩn với autoconf sẽ không được sử dụng, một số thay đổi trong tập tin tiêu đề cần phải được thực hiện. Đầu tiên của tất cả các chỉnh sửa util.h và thay thế dòng:

extern ieee754_float32_t fast_log2 (ieee754_float32_t x); 
với kiến trúc thực hiện sử dụng 32-bit float, mà chỉ đơn giản là nổi: 
fast_log2 phao extern (float x) ;. 
Trong set_get.h thay 
#include <lame.h>
với 
#include "lame.h".

III. Build thư viện LAME MP3 cho Android

Bây giờ tạo Makefile cho NDK và bao gồm các tập tin nguồn LAME. Các tập tin nên được đặt tên Android.mk và được đặt trong thư mục JNI. Nó sẽ giống như thế này:

LOCAL_PATH := $(call my-dir)
 
		include $(CLEAR_VARS)
		 
		LOCAL_MODULE    	:= libmp3lame
		LOCAL_SRC_FILES 	:= \
		./libmp3lame/bitstream.c \
		./libmp3lame/encoder.c \
		./libmp3lame/fft.c \
		./libmp3lame/gain_analysis.c \
		./libmp3lame/id3tag.c \
		./libmp3lame/lame.c \
		./libmp3lame/mpglib_interface.c \
		./libmp3lame/newmdct.c \
		./libmp3lame/presets.c \
		./libmp3lame/psymodel.c \
		./libmp3lame/quantize.c \
		./libmp3lame/quantize_pvt.c \
		./libmp3lame/reservoir.c \
		./libmp3lame/set_get.c \
		./libmp3lame/tables.c \
		./libmp3lame/takehiro.c \
		./libmp3lame/util.c \
		./libmp3lame/vbrquantize.c \
		./libmp3lame/VbrTag.c \
		./libmp3lame/version.c
		
		LOCAL_LDLIBS := -llog
		
		include $(BUILD_SHARED_LIBRARY)

Các thư viện chia sẻ bây giờ có thể được xây dựng. Tới thư mục JNI và gọi ndk-xây dựng kịch bản từ đó. Một trình biên dịch thích hợp sẽ cung cấp cho một đầu ra như thế này:

[…]
		SharedLibrary  : libmp3lame.so
		Install        : libmp3lame.so => libs/armeabi/libmp3lame.so		
		There should be new folders in the project root: libs and obj.

III. Tạo một ứng dụng Android

Tạo một ứng dụng Android Kể từ khi một wrapper chức năng cho các bộ mã hóa đã được thực hiện, nó có thể được sử dụng trong mã Java. Đầu tiên, để cho âm thanh ghi lại ứng dụng và truy cập vào thẻ SD để lưu trữ các tập tin nguyên và mã hóa bằng cách bổ sung các điều khoản Android yêu cầu: RECORD_AUDIO và WRITE_EXTERNAL_STORAGE.

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <android/log.h> 
#include "libmp3lame/lame.h"

#define LOG_TAG "LAME ENCODER"
#define LOGD(format, args...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, format, ##args);
#define BUFFER_SIZE 8192
#define be_short(s) ((short) ((unsigned short) (s) << 8) | ((unsigned short) (s) >> 8))

lame_t lame;

int read_samples(FILE *input_file, short *input) {
	int nb_read;
	nb_read = fread(input, 1, sizeof(short), input_file) / sizeof(short);

	int i = 0;
	while (i < nb_read) {
		input[i] = be_short(input[i]);
		i++;
	}

	return nb_read;
}

void Java_com_samsung_sample_lame4android_LameActivity_initEncoder(JNIEnv *env,
		jobject jobj, jint in_num_channels, jint in_samplerate, jint in_brate,
		jint in_mode, jint in_quality) {
	lame = lame_init();

	LOGD("Init parameters:");
	lame_set_num_channels(lame, in_num_channels);
	LOGD("Number of channels: %d", in_num_channels);
	lame_set_in_samplerate(lame, in_samplerate);
	LOGD("Sample rate: %d", in_samplerate);
	lame_set_brate(lame, in_brate);
	LOGD("Bitrate: %d", in_brate);
	lame_set_mode(lame, in_mode);
	LOGD("Mode: %d", in_mode);
	lame_set_quality(lame, in_quality);
	LOGD("Quality: %d", in_quality);

	int res = lame_init_params(lame);
	LOGD("Init returned: %d", res);
}

void Java_com_samsung_sample_lame4android_LameActivity_destroyEncoder(
		JNIEnv *env, jobject jobj) {
	int res = lame_close(lame);
	LOGD("Deinit returned: %d", res);
}

void Java_com_samsung_sample_lame4android_LameActivity_encodeFile(JNIEnv *env,
		jobject jobj, jstring in_source_path, jstring in_target_path) {
	const char *source_path, *target_path;
	source_path = (*env)->GetStringUTFChars(env, in_source_path, NULL);
	target_path = (*env)->GetStringUTFChars(env, in_target_path, NULL);

	FILE *input_file, *output_file;
	input_file = fopen(source_path, "rb");
	output_file = fopen(target_path, "wb");

	short input[BUFFER_SIZE];
	char output[BUFFER_SIZE];
	int nb_read = 0;
	int nb_write = 0;
	int nb_total = 0;

	LOGD("Encoding started");
	while (nb_read = read_samples(input_file, input)) {
		nb_write = lame_encode_buffer(lame, input, input, nb_read, output,
				BUFFER_SIZE);
		fwrite(output, nb_write, 1, output_file);
		nb_total += nb_write;
	}
	LOGD("Encoded %d bytes", nb_total);

	nb_write = lame_encode_flush(lame, output, BUFFER_SIZE);
	fwrite(output, nb_write, 1, output_file);
	LOGD("Flushed %d bytes", nb_write);

	fclose(input_file);
	fclose(output_file);
}

Bước tiếp theo là để tải các thư viện bản xứ. Do nó trong một khối tĩnh, vì vậy nó được thực hiện một lần duy nhất. Sau đó khai báo các phương pháp bản địa:

static {
                    System.loadLibrary("mp3lame");
                }
                private native void initEncoder(int numChannels, int sampleRate, int bitRate, int mode, int quality);
                private native void destroyEncoder();
                private native int encodeFile(String sourcePath, String targetPath);

Bây giờ họ có thể được sử dụng như bình thường. Các ứng dụng mẫu giao với bài viết này có một bố cục đơn giản với một nút, mà bắt đầu hoặc dừng ghi âm. Bộ ghi và mã hóa được khởi động ngay từ đầu. Sau khi nhấn vào nút để bắt đầu, các ứng dụng sẽ bắt đầu thu âm và ghi nó vào đầu ra đệm. Khi quyết định dừng lại, chụp âm thanh sẽ bị gián đoạn và các dữ liệu bị bắt sẽ được chuyển cho các bộ mã hóa. Khi mã hóa được hoàn tất, người dùng sẽ được thông báo với các tên tập tin được mã hóa. Khi các ứng dụng kết thúc, máy ghi âm và mã hóa được phát hành.

Nguồn dịch từ Tài liệu kĩ thuật của Samsung.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí