我试图将 char* 转换为 float*

Posted

技术标签:

【中文标题】我试图将 char* 转换为 float*【英文标题】:Im trying to convert a char* to float* 【发布时间】:2020-08-22 11:45:43 【问题描述】:

我正在尝试使用 ALSA 录制音频并将其传递给进行处理。音频样本从 this 返回,它是 char* 到 float*

我尝试了很多解决方案,我想我明白它不是真正的字符缓冲区而是字节缓冲区,而是我如何让它成为浮点数。

这会返回缓冲区:

const unsigned char* arBuffer(void)

    return buffer;

我需要将麦克风的输出作为浮点数消耗

 int32_t O_DecodeAudioBuffer(float *audioBuffer, int size, void *oxyingObject)

  Core *oxying = (COxyCore*)oxyingObject;

  //Decode audioBuffer to check if begin token is found, we should keep previous buffer to check if token was started in previous
  //var mDecoding > 0 when token has been found, once decoding is finished, mDecoding = 0
  return oxying->mDecoder->DecodeAudioBuffer(audioBuffer, size);

我正在编写一个程序以将上述内容作为 api 使用:

void* mOxyCore; is declared

然后我尝试传递无法按预期工作的 arBuffer()。

while(arIsRunning())
    

        int ret = DecodeAudioBuffer(arBuffer(), arBufferSize(), mCore);
    

阿尔萨:

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API

#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <pthread.h>
#include "settings.h"
#include "audiorecorder.h"


pthread_t thr;
pthread_mutex_t mutex;
snd_pcm_t *handle;
snd_pcm_uframes_t frames;
unsigned char* buffer;
BOOL running;
size_t buffersize;


BOOL arIsRunning(void)

    return running;



void arAcquireBuffer(void)

    //printf("Acquired buffer\n");
    pthread_mutex_lock(&mutex);



void arReleaseBuffer(void)

    //printf("Released buffer\n");
    pthread_mutex_unlock(&mutex);



const unsigned char* arBuffer(void)

    return buffer;



const size_t arBufferSize(void)

    return buffersize;



void* entry_point(void *arg)

    int rc;

    fprintf(stderr, "Listening...\n");

  while (running)
    
        arAcquireBuffer();
    rc = snd_pcm_readi(handle, buffer, frames);

    //stream to stdout - useful for testing/debugging
    //write(1, buffer, buffersize);
        arReleaseBuffer();

    if (rc == -EPIPE) 
      /* EPIPE means overrun */
      fprintf(stderr, "overrun occurred\n");
      snd_pcm_prepare(handle);
    
        else if (rc < 0) 
      fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
            running = FALSE;
    
        else if (rc != (int)frames) 
      fprintf(stderr, "short read, read %d frames\n", rc);
    
 

    return NULL;




int arInitialise(void)

  snd_pcm_hw_params_t *params;
  unsigned int val;
  int rc, dir;

    running = FALSE;

  /* Open PCM device for recording (capture). */
  rc = snd_pcm_open(&handle, RECORDER_DEVICE, SND_PCM_STREAM_CAPTURE, 0);
  if (rc < 0) 
    fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
    return rc;
  
    else
    
        fprintf(stderr, "Successfully opened default capture device.\n");
    

  /* Allocate a hardware parameters object. */
  snd_pcm_hw_params_alloca(&params);

  /* Fill it in with default values. */
  snd_pcm_hw_params_any(handle, params);

  /* Set the desired hardware parameters. */

  /* Interleaved mode */
  snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

  /* Signed 16-bit little-endian format */
  snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    fprintf(stderr, "Format set to PCM Signed 16bit Little Endian.\n");


  /* Channels */
  snd_pcm_hw_params_set_channels(handle, params, NUM_CHANNELS);
    fprintf(stderr, "Channels set to %d.\n", NUM_CHANNELS);


  /* sampling rate */
  val = SAMPLE_RATE;
  snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
    fprintf(stderr, "Samplerate set to %d.\n", val);

  /* Set period to FRAMES_PER_BUFFER frames. */
  frames = FRAMES_PER_BUFFER;
  snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

  /* Write the parameters to the driver */
  rc = snd_pcm_hw_params(handle, params);
  if (rc < 0) 
    fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
    return rc;
  

  /* Use a buffer large enough to hold one period */
  snd_pcm_hw_params_get_period_size(params, &frames, &dir);
  buffersize = frames * 2 * NUM_CHANNELS; /* 2 bytes/sample * channels */
  buffer = (unsigned char*) malloc(buffersize);

  /* We want to loop forever */
  //snd_pcm_hw_params_get_period_time(params, &val, &dir);

  return 0;



int arStartRecording(void)

    if(running) return 1;

  if(pthread_mutex_init(&mutex, NULL))
  
    printf("Unable to initialize mutex\n");
    return -1;
  

  if(pthread_create(&thr, NULL, &entry_point, NULL))
  
    fprintf(stderr, "Could not create recorder thread!\n");
        running = FALSE;
    return -1;
  

    running = TRUE;
    return 0;



void arStopRecording(void)

    running = FALSE;



void arFree(void)

    running = FALSE;
    sleep(500);
  snd_pcm_drain(handle);
  snd_pcm_close(handle);
  pthread_mutex_destroy(&mutex);
  free(buffer);

【问题讨论】:

***.com/questions/18494218/… 请看看这个 谢谢,我已经看到答案,我遇到的问题是不允许从 'const unsigned char *' 到 'float' 的 C 风格转换。 Alsa记录器是c,主程序是c++ Decoder::DecodeAudioBuffer 正在写信给audioBuffer 吗?如果是这样,arBuffer() 是否有意返回const char*?也许提供一个minimal reproducible example(例如,mCore 是什么,为什么将它作为参数传递给不接受它的函数?) 我已经更新了我的答案,谢谢你的帮助。 arBuffer() 是故意返回的 const char* 是他们的另一种方式? Decoder::DecodeAudioBuffer 函数正在写入,然后分析令牌 【参考方案1】:

这里的问题不是演员表,而是表示问题。

音频通常表示为一系列样本。有很多方法可以表示每个样本:从-1.0f+1.0f,或从-32767+32767,或许多其他方式。

Alsa 实际上支持many formats,而您选择了SND_PCM_FORMAT_S16_LE,所以这是-32767+32767。假设您的 C++ 环境是 Little-Endian(几乎可以肯定),您可以将其转换为 std::int16_t*。您不能将其转换为float*,因为您需要请求SND_PCM_FORMAT_FLOAT_LE

【讨论】:

更改格式并执行此操作后 //Cast to float float value = ((float)arBuffer());我在打印时得到像 1.46939e-39 这样的数字我希望这越来越接近 @JJohn:嗯,现在你有一个转换错误。你应该创建一个std::vector&lt;float&gt; values;你不会得到一个单一的价值。将其调整为arBufferSize()/sizeof(float),然后将memcpyarBuffer 调整为&amp;values[0] 非常感谢您再次为我指明正确的方向 我不得不再次向社区提出另一个问题希望我能掌握这个***.com/questions/61676227/…

以上是关于我试图将 char* 转换为 float*的主要内容,如果未能解决你的问题,请参考以下文章

将 char[] 转换为 float 或 double - c++

为啥编译器试图将 char * 转换为 char? [关闭]

c语言里怎么把float转换为char型?

Arduino中数据类型转换 float/double转换为char 亲测好使,dtostrf()函数

错误:无法将“char (*)[6]”转换为“char**”

Arduino中数据类型转换 float/double转换为char 亲测好使,dtostrf()函数