Ioctl "can't send spi message: Invalid argument" Beaglebone Black - c

I am attempting to send 16-bit messages from my beaglebone black on spidev1.0 (bus 1 device 0) to an IC chip TLV5618AC
The chip-select line needs to go from high to low before the shift registers start picking up bits on the falling edge of the clock.
I performed a modified version of spidev_test.c (the original worked fine). Since I need the chip select line to go from high to low between messages - the line ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); will not work because it transmits the data as a single message. Even if I put ioctl() within a for loop it would not work because it is the first and last message.
The following code works
static void transfer(int fd)
{
int ret;
unsigned short buffer[1];
int zero = 0;
FILE *iFile = fopen("firsttest.bin", "r");
if (iFile == NULL)
{
printf("Cannot open file \n");
exit(0);
}
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)zero,
.rx_buf = (unsigned long)zero,
.len = 2,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
while(!feof(iFile)){
fread(buffer,2,1,iFile);
unsigned short *tx = buffer;
unsigned short rx[1] = {0, };
tr.tx_buf = (unsigned long)tx;
tr.rx_buf = (unsigned long)rx;
int size = ARRAY_SIZE(tx);
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
for (ret = 0; ret < 1; ret++) {
printf("0x%04x\n", tx[ret]);
}
}
}
This second block of code does not
{
int ret;
unsigned short buffer[1];
int zero = 0;
FILE *iFile = fopen("firsttest.bin", "r");
if (iFile == NULL)
{
printf("Cannot open file \n");
exit(0);
}
struct spi_ioc_transfer tr[100];
unsigned short *p = (unsigned short*) calloc(100, sizeof(unsigned short));
unsigned short *p2 = (unsigned short*) calloc(100, sizeof(unsigned short));
while(!feof(iFile)){
unsigned short *tx = p2;
unsigned short *rx=p;
for(int j = 0; j< 100; j++){
fread(buffer,2,1,iFile);
tx = (unsigned short*) &buffer+j;
tr[j].tx_buf = (unsigned long)tx;
tr[j].rx_buf = 0;
tr[j].len = 2;/* Total length of message in bytes*/
tr[j].delay_usecs = delay;
tr[j].speed_hz = speed;
tr[j].bits_per_word = bits;
tr[j].cs_change = 1;
}
ret = ioctl(fd, SPI_IOC_MESSAGE(100), &tr);
if (ret < 1)
pabort("can't send spi message");
for(int v = 0; v<100; v++){
printf("0x%04x\n", rx);
}
}
free(p);
}
The second block of code yield this error
"can't send spi message: Invalid argument"
Since it is an invalid argument, I tried passing in '&tr' as well as 'tr' to no avail. Any input would be appreciated.
EDIT: So I resolved to use the first code which worked. I guess there is no reason to send large transfers. My system is fast enough to where the voltages are fast enough to effectively be real time!! Thanks for the help. (I also cleaned up my code a lot to make it easier to read!)

add memset(&tr, 0, sizeof(tr)); after struct spi_ioc_transfer tr
https://community.nxp.com/thread/482375

Looking through this, it occurs to me that you may not be defining your tr[j].rx_buf correctly, and this would lead to the invalid argument. There needs to be an allocated storage which I assume is *p, but you aren't associating that with the tr argument.

Related

Alsa plays audio get from CAN FD

I am trying to use Alsa library to reproduce the audio I get from my CAN FD communication, into my headphones. I don't quite understand how to properly configure Alsa's parameters, in order to be able to listen to the sound I get from the CAN FD.
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; /* sample format */
static unsigned int rate = 16000; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 40000; /* ring buffer length in us */
static unsigned int period_time = 120000; /* period time in us */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
int size;
while (1) {
do {
nbytes = read(s, &frame, sizeof(struct canfd_frame));
} while (nbytes == 0);
for (x = 0; x < 64; x = x + 2) {
buffer[a] = ((uint32_t) frame.data[x] << 8)
| ((uint32_t) (frame.data[x + 1]));
a++;
}
//err=snd_pcm_writei(handle,buffer,32);
//printf("Datos = %d\n", err);
memcpy(total1 + i * 32, buffer, 32 * sizeof(uint32_t));
i++;
a = 0;
if (i == 500) {
buffer_length=16000;
ptr = total1;
while(buffer_length > 0){
err = snd_pcm_writei(handle, ptr, 16000);
printf("Datos = %d\n", err);
snd_pcm_avail_delay(handle, &availp, &delayp);
//printf("available frames =%ld delay = %ld z = %d\n", availp, delayp, z);
if (err == -EAGAIN)
continue;
if(err < 0){
err=snd_pcm_recover(handle, err, 1);
}
else{
ptr += err * channels;
buffer_length -= err;
z++;
}
if(err<0){
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
i = 0;
}
This is a part of my code, I don't thinks posting the whole code is worth. I don't understand which values should I give to buffer_time, period_time and how to be able to listen to what a I get through the CAN FD in real time. I am using snd_pcm_writei, inserting a buffer I fill with some samples I get from the CAN FD. I don't know which size should I give to the buffer and to the "frames" variable, another one that I don't quite understand, eventhough I have read some about it.
Any idea how should I configure my system? (buffer_time, period_time, buffer_size, frame,...)
I have tried using different buffer and frame sizes, but I don't think I understand how it works properly. How can I calculate the size of the frame and buffer of the snd_pcm_writei(), in order to listen in Real Time to the audio?
Should I use two differente threads? One to create the buffer with the CAN FD information and the other one to handle the buffer and the audio output?
Thanks in advance,
Ander.
I have finally managed to hear my self through the headphones. I have changed my configuration posted on my previous in order to sincronize it with the data I get from the CAN FD. I will post part of my code down here in case somebody needs an example. The most important part having to handle buffers like these is to handle the time to fill and the time to communicate it. Handling the time and configuring the Alsa parameters accordingly makes easier to handle the buffers.
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; /* sample format */
static unsigned int rate = 22000; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 1000; /* ring buffer length in us */
static unsigned int period_time = 10000; /* period time in us */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
int size;
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
snd_pcm_sframes_t delayp;
snd_pcm_sframes_t availp;
snd_pcm_uframes_t frames;
static void write_loop(snd_pcm_t *handle) {
uint32_t *buffer = malloc(16000 * sizeof(uint32_t));
uint32_t *total1 = malloc(16000 * sizeof(uint32_t)); // array to hold the result
while (1) {
do {
nbytes = read(s, &frame, sizeof(struct canfd_frame));
} while (nbytes == 0);
for (x = 0; x < 64;x = x + 2) {
buffer[a] = ((uint32_t) frame.data[x] << 8)
| ((uint32_t) (frame.data[x + 1]));
//buffer[a]=frame.data[x];
a++;
}
i++;
if (i == 250) {
memcpy(total1, buffer, 16000 * sizeof(uint32_t));
//printf("Address = %lu \n",(unsigned long)total1);
flag = 1;
buffer_length = 16000;
i = 0;
a = 0;
}
if (flag == 1) {
while(buffer_length > 0) {
snd_pcm_prepare(handle);
err = snd_pcm_writei(handle, total1, buffer_length);
//printf("Datos = %d\n", err);
snd_pcm_avail_delay(handle, &availp, &delayp);
//printf("available frames =%ld delay = %ld\n",availp,delayp);
if (err == -EAGAIN)
continue;
if (err < 0) {
err = snd_pcm_recover(handle, err, 1);
} else {
ptr += err * channels;
buffer_length -= err;
z++;
}
if (err < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
flag = 0;
}
}
}

Alsa lib 32 bits

I've been trying to use the ALSA lib for a while and I don't understand how I should use it.
I took an example program and I've tried to modify it to use float (32bits) instead of unsigned char (8bits). But now when I'm running it, I have a segmentation fault in the second loop.
Here is my code :
#include <alsa/asoundlib.h>
snd_pcm_t *create_pcm(const char* name, snd_pcm_stream_t mode, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int nbChannel, unsigned int rate, int softSample, unsigned int latency)
{
int err;
snd_pcm_t *handle;
if ((err = snd_pcm_open(&handle, name, mode, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
if ((err = snd_pcm_set_params(handle,
format,
access,
nbChannel,
rate,
softSample,
latency)) < 0) { /* 0.5sec */
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
return handle;
}
int main(void)
{
unsigned int i;
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
float buffer[16*1024]; /* some random data */
handle = create_pcm("default", // name of the device used by the sound card
SND_PCM_STREAM_PLAYBACK, // to use the device in output
SND_PCM_FORMAT_FLOAT, // use the device with 32bit depth (float)
SND_PCM_ACCESS_RW_INTERLEAVED,
1, // use 1 channel
48000, // use 48000 Hz (dvd quality)
1, // soft resample ON
500000); // 0.5s of latency
// building random data
for(i = 0; i < sizeof(buffer); i++)
buffer[i] = i % 255; // random();
for (i = 0; i < 16; i++) {
frames = snd_pcm_writei(handle, buffer, sizeof(buffer)); // segmentation fault
if(frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
break;
}
if (frames > 0 && frames < (long)sizeof(buffer))
printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), frames);
}
snd_pcm_close(handle);
return 0;
}
How to use this lib with 32bits?
I've tried this format and others like little endian or big endian.. The only one that doesn't crash is SND_PCM_FORMAT_FLOAT but it's making the error :
ALSA lib pcm.c:8507:(snd_pcm_set_params) Sample format not available for PLAYBACK: Invalid argument
Playback open error: Invalid argument
Thanks in advance.
P.S.: Linux, Ubuntu 19.10 64bits
The segmentation fault may already occur when you write into buffer:
for(i = 0; i < sizeof(buffer); i++)
buffer[i] = i % 255; // random();
sizeof(buffer) will give you the size in bytes not the number of elements. They are only equal for char (and unsigned char) since sizeof(char) is 1. You most likely want to iterate over the elements:
for(i = 0; i < sizeof buffer/sizeof *buffer; i++)
buffer[i] = i % 255; // random();
It was indeed a problem of condition in my loop and my snd_pcm_writei()
Here is the code without errors thanks to #Osiris :
#include <alsa/asoundlib.h>
snd_pcm_t *create_pcm(const char* name, snd_pcm_stream_t mode, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int nbChannel, unsigned int rate, int softSample, unsigned int latency)
{
int err;
snd_pcm_t *handle;
if ((err = snd_pcm_open(&handle, name, mode, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
if ((err = snd_pcm_set_params(handle,
format,
access,
nbChannel,
rate,
softSample,
latency)) < 0) { /* 0.5sec */
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
return handle;
}
int main(void)
{
unsigned int i;
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
float buffer[16*1024]; /* some random data */
handle = create_pcm("default", // name of the device used by the sound card
SND_PCM_STREAM_PLAYBACK, // to use the device in output
SND_PCM_FORMAT_FLOAT, // use the device with 32bit depth (float)
SND_PCM_ACCESS_RW_INTERLEAVED,
1, // use 1 channel
48000, // use 48000 Hz (dvd quality)
1, // soft resample ON
500000); // 0.5s of latency
// building random data
for(i = 0; i < sizeof(buffer) / sizeof(*buffer); i++)
buffer[i] = i % 0xffffffff; // random();
for (i = 0; i < 16; i++) {
frames = snd_pcm_writei(handle, buffer, sizeof(buffer) / sizeof(*buffer)); // segmentation fault
if(frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
break;
}
if (frames > 0 && frames < (long)(sizeof(buffer) / sizeof(*buffer)))
printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), frames);
}
snd_pcm_close(handle);
return 0;
}

Linux C code crashes

I wrote a C program on the Beaglebone Black to read and write to the 25LC256 (EEPROM). I am able to compile it without any errors or warnings, gcc SPI.c -o SPI, but when I try running it ./SPI, my entire Beaglebone stops working, and I have to reboot it. In fact, the program doesn't even output anything. I have the code print out "Starting" at the begging, but that doesn't even work.
Could anybody see where I might be going wrong ?
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
//You need to correctly identify the SPI device bus and number
int write64NVM(int fd, unsigned char data[], int length, unsigned int add);
int read64NVM(int fd, unsigned char to[], int length, unsigned int add);
static const char *device = "/dev/spidev1.0";
int main(){
uint8_t mode=0, bits=8;
uint32_t speed=500000;
int file;
printf("Starting");
if ((file = open(device, O_RDWR))<0){
perror("SPI: Can't open device.");
return -1;
}
if (ioctl(file, SPI_IOC_WR_MODE, &mode)==-1){
perror("SPI: Can't set SPI mode.");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MODE, &mode)==-1){
perror("SPI: Can't get SPI mode.");
return -1;
}
if (ioctl(file, SPI_IOC_WR_BITS_PER_WORD, &bits)==-1){
perror("SPI: Can't set bits per word.");
return -1;
}
if (ioctl(file, SPI_IOC_RD_BITS_PER_WORD, &bits)==-1){
perror("SPI: Can't get bits per word.");
return -1;
}
if(ioctl(file, SPI_IOC_WR_MAX_SPEED_HZ, &speed)==-1){
perror("SPI: Can't set max speed HZ");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MAX_SPEED_HZ, &speed)==-1){
perror("SPI: Can't get max speed HZ.");
return -1;
}
printf("spi mode: 0x%xn", mode);
printf("bits per word: %dn", bits);
printf("max speed: %d Hz (%d KHz)n", speed, speed/1000);
// sending one byte on the MOSI line and receiving the data on MISO
write64NVM(file, "hello", 6, 0);
close(file);
return 0;
}
int write64NVM(int fd, unsigned char data[], int length, unsigned int add)
{
unsigned char InstructionBuffer[1], AddressBuffer[3];
int status;
//DataBuffer = (char *) malloc(length);
struct spi_ioc_transfer xfer[3];
InstructionBuffer[0] = 6; //Set the write enable latch (enable write operations)
AddressBuffer[0] = 2; //Write data to memory array beginning at selected address
AddressBuffer[1] = (add >> 8);
AddressBuffer[2] = (add & 0b11111111);
//DataBuffer = data;
//First Transaction
xfer[0].tx_buf = (unsigned long)InstructionBuffer;
xfer[0].rx_buf = (unsigned long)NULL;
xfer[0].len = 1;
xfer[0].cs_change = 1;
//Second transaction
xfer[1].tx_buf = (unsigned long)AddressBuffer;
xfer[1].rx_buf = (unsigned long)NULL;
xfer[1].len = 3;
xfer[1].cs_change = 0;
//Third transaction
xfer[2].tx_buf = (unsigned long)data;
xfer[2].rx_buf = (unsigned long)NULL;
xfer[2].len = length;
xfer[2].cs_change = 1;
status = ioctl(fd, SPI_IOC_MESSAGE(3), &xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE error");
return;
}
return status;
}
int read64NVM(int fd, unsigned char to[], int length, unsigned int add){
//Read Sequence :
//Pull ~CS low
//The 8-bit instruction is transmited to EEPROM followed
//by 16-bit address, with first MSB of the address being a 'dont care'
//bit.
//According to Page 7 Figure 2-1 of the 25LC256.pdf, to read an address from
//EEPROM, the BBB must only send out 2 transactions. The instruction and the address.
//In this case, the instruction is read, so the value of transaction is 3.
//~CS apears to be kept low throughout the entire transaction until data
//has completely been shifted out of EEPROM.
//Like in write64NVM, there are 3 buffers
//unsigned char InstructionBuffer, AddressBuffer[3], DataBuffer[8],
//but the latter will be used to store the Data recieved.
unsigned char InstructionBuffer, AddressBuffer[2], *DataBuffer;
int status;
//DataBuffer = (char *) malloc(length);
struct spi_ioc_transfer xfer[3];
InstructionBuffer = 3; //Read intruction value
//AddressBuffer[0] = 2;
AddressBuffer[0] = add >> 8;
AddressBuffer[1] = add & 0b11111111;
DataBuffer = 0;
//First Transaction
xfer[0].tx_buf = (unsigned long)&InstructionBuffer;
xfer[0].rx_buf = (unsigned long)NULL;
xfer[0].len = 1;
xfer[0].cs_change = 1;
//Second transaction
xfer[1].tx_buf = (unsigned long)AddressBuffer;
xfer[1].rx_buf = (unsigned long)NULL;
xfer[1].len = 2;
xfer[1].cs_change = 0;
//Third transaction
xfer[2].tx_buf = (unsigned long)NULL;
xfer[2].rx_buf = (unsigned long)to;
xfer[2].len = length;
xfer[2].cs_change = 1;
status = ioctl(fd, SPI_IOC_MESSAGE(3), &xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE error");
return;
}
return status;
}
Please forgive my poor coding, I'm still a beginner.

read()/ioctl disturbs GPIO signal?

I connect a Linux embedded board(based on imx233) and a MSP430 MCU. They are connected via 4 pin SPI, but I use a GPIO for the chip select purpose on the Linux board. What I do is to use poll to detect falling edge of the GPIO(nr 52) then perform SPI reading either ioctl or read()
int main(void)
{
/********************************LINUX SCHEDULING**********************************/
sp.sched_priority = sched_get_priority_max(SCHED_FIFO); //scheduling
sched_setscheduler(0, SCHED_FIFO, &sp); //scheduling
/********************************LINUX SCHEDULING_END******************************/
struct pollfd fdset[2]; //declare the poll to be used in interrupt catching
int nfds = 2;
int gpio_fd, timeout, rc;
char *buf[MAX_BUF]; //max=64byte
int len;
initialize(); //gpio's are set to SPI_SLAVE
// spi_init();
gpio_fd = gpio_fd_open(CHIP_SELECT_PIN); //the CS(SS) pin is opened
timeout = POLL_TIMEOUT; //timeout 3 sec is set
// uint8_t voidFirstDetection = 1;
while (1) {
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = NULL;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
/*** POLL starts to detect chipselects****/
rc = poll(fdset, nfds, timeout);
if (rc < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0) {
printf(".");
}
if (fdset[1].revents & POLLPRI ) { //HERE I need to run SPI_read
len = read(fdset[1].fd, buf, MAX_BUF);
/* if(voidFirstDetection){
voidFirstDetection = 0;
}else{*/
printf("\npoll() GPIO %d interrupt occurred\n", CHIP_SELECT_PIN);
int fd = open(device, O_RDWR);
if (fd < 0){
// snprintf(systemlogmsg, sizeof(systemlogmsg), "[1181]: errno:%s Cannot open /dev/spidev ", strerror(errno));
// error_logging(systemlogmsg, LOGLEVEL_ERROR);
printf("error spi recive\n");
}
//spi_transfer(fd);
do_read(fd);
close(fd);
// }
}
}
gpio_fd_close(gpio_fd);
return 0;
}
Above code works fine that it generates an interrupt only at the falling edge of the signal. I use the either of the below code when the interrupt is detected to read the /dev/spidev1-0
static void do_read(int fd)
{
unsigned char buf[1], *bp;
int status;
int len = 1;
/* read at least 2 bytes, no more than 32 */
memset(buf, 0, sizeof buf);
status = read(fd, buf, len);
if (status < 0) {
perror("read");
return;
}
if (status != len) {
fprintf(stderr, "short read\n");
return;
}
printf("read(%2d, %2d): %02x %02x,", len, status,
buf[0], buf[1]);
status -= 2;
bp = buf + 2;
while (status-- > 0)
printf(" %02x", *bp++);
printf("\n");
}
static void spi_transfer(int fd)
{
int ret;
uint8_t tx[2];
uint8_t rx[3] = {0 };
struct spi_ioc_transfer tr = {
.tx_buf = 0,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1){
printf("can't send spi message");
exit(1);
}
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
if (!(ret % 6))
puts("");
printf("%.2X ", rx[ret]);
}
puts("");
}
Whenever the either ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); line on spi_transfer() or status = read(fd, buf, len); on do_read() is executed, I see an infinite loop that detects an interrupt on the GPIO52 (chipselect). I try the observe the GPIO via oscilloscope but I could not see any signal change (it might be a spike that my oscilloscope cannot detect), however, when I connect the chipselect to the Vcc, it does not get the infinite loop. As I am on the early stage, I set one of GPIO of the MCU as an output and a constant logic high. I use GPIO52 (Chip select) as an input because my aim is to transfer data from MCU to the linux board.
I guess, the read() and ioctl somehow effects the GPIO to sink more current than the GPIO can provide. If it is the problem, what can I do that ioctl or read() would not disturb GPIO. Or do you think something else could be a problem?
I was lucky that I found the problem quick. I tied the grounds of both boards and now it works fine. I will keep the post as someone else might have the same problem. But I am still curious how ioctl or read disturbs the GPIO signal level

How to use LAME API in C? Is there any simple example?

Is there any simple example (with explanations) of how to use LAME API in C? I did manage to use the following code (based on Is there any LAME c++ wraper\simplifier (working on Linux Mac and Win from pure code)?):
FILE *pcm = fopen(input_file, "rb");
FILE *mp3 = fopen(output_file, "wb");
size_t nread;
int ret, nwrite;
// 1. Get lame version (OPTIONAL)
printf("Using LAME v%s\n", get_lame_version());
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short pcm_buffer[PCM_SIZE * 2];
unsigned char mp3_buffer[MP3_SIZE];
// 2. Initializing
lame_t lame = lame_init();
// 3. Do some settings (OPTIONAL)
// lame_set_in_samplerate(lame, 48000);
lame_set_VBR(lame, vbr_default);
// lame_set_VBR_quality(lame, 2);
// 4. Initialize parameters
ret = lame_init_params(lame);
if (ret < 0) {
printf("Error occurred during parameters initializing. Code = %d\n",
ret);
return 1;
}
do {
// Read PCM_SIZE of array
nread = fread(pcm_buffer, 2 * sizeof(short), PCM_SIZE, pcm);
if (nread != 0) {
// 5. Encode
int nsamples = nread;
short buffer_l[nsamples];
short buffer_r[nsamples];
printf("nread = %d\n", nread);
printf("pcm_buffer.length = %d\n", sizeof(pcm_buffer)/sizeof(short));
int j = 0;
int i = 0;
for (i = 0; i < nsamples; i++) {
buffer_l[i] = pcm_buffer[j++];
buffer_r[i] = pcm_buffer[j++];
}
nwrite = lame_encode_buffer(lame, buffer_l, buffer_r, nread,
mp3_buffer, MP3_SIZE);
} else {
// 6. Flush and give some final frames
nwrite = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
}
if (nwrite < 0) {
printf("Error occurred during encoding. Code = %d\n", nwrite);
return 1;
}
fwrite(mp3_buffer, nwrite, 1, mp3);
} while (nread != 0);
// 7. Write INFO tag (OPTIONAL)
// lame_mp3_tags_fid(lame, mp3);
// 8. Free internal data structures
lame_close(lame);
fclose(mp3);
fclose(pcm);
But the thing is,
I don't understand why use
short pcm_buffer[PCM_SIZE * 2];
fread(pcm_buffer, 2 * sizeof(short), PCM_SIZE, pcm);
Instead of
short pcm_buffer[PCM_SIZE * 2];
fread(pcm_buffer, sizeof(short), PCM_SIZE * 2, pcm);
If I have to use the first way, how use get such pcm_buffer in Java? I want to use JNI
Is that a correct way to get 2 buffer (left and right)?
Thanks
1) I don't understand why use
pcm_buffer has space for PCM_SIZE*2 elements that each are sizeof(short) bytes large (typically 2 bytes). I.e. PCM_SIZE*2*sizeof(short) bytes in total.
That's why the fread is reading PCM_SIZE chunks of 2*sizeof(short), it's filling up the entire PCM_SIZE*2*sizeof(short) bytes in the buffer.

Resources