Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
Torchaudio
Commits
27e6779c
Unverified
Commit
27e6779c
authored
Sep 15, 2021
by
hwangjeff
Committed by
GitHub
Sep 15, 2021
Browse files
[fbsync] Style fixes (#1766)
Applies style fixes identified in fbcode.
parent
b00bacf7
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
96 additions
and
102 deletions
+96
-102
torchaudio/csrc/CMakeLists.txt
torchaudio/csrc/CMakeLists.txt
+1
-1
torchaudio/csrc/pybind/sox/effects.cpp
torchaudio/csrc/pybind/sox/effects.cpp
+5
-7
torchaudio/csrc/pybind/sox/effects.h
torchaudio/csrc/pybind/sox/effects.h
+5
-7
torchaudio/csrc/pybind/sox/effects_chain.cpp
torchaudio/csrc/pybind/sox/effects_chain.cpp
+20
-22
torchaudio/csrc/pybind/sox/effects_chain.h
torchaudio/csrc/pybind/sox/effects_chain.h
+2
-4
torchaudio/csrc/pybind/sox/io.cpp
torchaudio/csrc/pybind/sox/io.cpp
+20
-13
torchaudio/csrc/pybind/sox/io.h
torchaudio/csrc/pybind/sox/io.h
+6
-9
torchaudio/csrc/pybind/sox/utils.cpp
torchaudio/csrc/pybind/sox/utils.cpp
+4
-5
torchaudio/csrc/pybind/sox/utils.h
torchaudio/csrc/pybind/sox/utils.h
+3
-5
torchaudio/csrc/sox/effects.cpp
torchaudio/csrc/sox/effects.cpp
+13
-12
torchaudio/csrc/sox/effects.h
torchaudio/csrc/sox/effects.h
+10
-11
torchaudio/csrc/sox/effects_chain.cpp
torchaudio/csrc/sox/effects_chain.cpp
+1
-1
torchaudio/csrc/sox/effects_chain.h
torchaudio/csrc/sox/effects_chain.h
+3
-3
torchaudio/csrc/sox/io.h
torchaudio/csrc/sox/io.h
+3
-2
No files found.
torchaudio/csrc/CMakeLists.txt
View file @
27e6779c
...
...
@@ -94,7 +94,7 @@ if (BUILD_TORCHAUDIO_PYTHON_EXTENSION)
if
(
BUILD_SOX
)
list
(
APPEND
EXTENSION_SOURCES
EXTENSION_SOURCES
pybind/sox/effects.cpp
pybind/sox/effects_chain.cpp
pybind/sox/io.cpp
...
...
torchaudio/csrc/pybind/sox/effects.cpp
View file @
27e6779c
...
...
@@ -4,8 +4,7 @@
using
namespace
torchaudio
::
sox_utils
;
namespace
torchaudio
{
namespace
sox_effects
{
namespace
torchaudio
::
sox_effects
{
// Streaming decoding over file-like object is tricky because libsox operates on
// FILE pointer. The folloing is what `sox` and `play` commands do
...
...
@@ -28,12 +27,12 @@ namespace sox_effects {
// fileobj. This will trick libsox as if it keeps reading from the FILE*
// continuously.
// For Step 2. see `fileobj_input_drain` function in effects_chain.cpp
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
apply_effects_fileobj
(
auto
apply_effects_fileobj
(
py
::
object
fileobj
,
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
,
const
std
::
vector
<
std
::
vector
<
std
::
string
>>
&
effects
,
c10
::
optional
<
bool
>
normalize
,
c10
::
optional
<
bool
>
channels_first
,
c10
::
optional
<
std
::
string
>
format
)
{
c10
::
optional
<
std
::
string
>
format
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
{
// Prepare the buffer used throughout the lifecycle of SoxEffectChain.
//
// For certain format (such as FLAC), libsox keeps reading the content at
...
...
@@ -115,5 +114,4 @@ std::tuple<torch::Tensor, int64_t> apply_effects_fileobj(
tensor
,
static_cast
<
int64_t
>
(
chain
.
getOutputSampleRate
()));
}
}
// namespace sox_effects
}
// namespace torchaudio
}
// namespace torchaudio::sox_effects
torchaudio/csrc/pybind/sox/effects.h
View file @
27e6779c
...
...
@@ -3,17 +3,15 @@
#include <torch/extension.h>
namespace
torchaudio
{
namespace
sox_effects
{
namespace
torchaudio
::
sox_effects
{
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
apply_effects_fileobj
(
auto
apply_effects_fileobj
(
py
::
object
fileobj
,
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
,
const
std
::
vector
<
std
::
vector
<
std
::
string
>>
&
effects
,
c10
::
optional
<
bool
>
normalize
,
c10
::
optional
<
bool
>
channels_first
,
c10
::
optional
<
std
::
string
>
format
);
c10
::
optional
<
std
::
string
>
format
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
;
}
// namespace sox_effects
}
// namespace torchaudio
}
// namespace torchaudio::sox_effects
#endif
torchaudio/csrc/pybind/sox/effects_chain.cpp
View file @
27e6779c
...
...
@@ -4,8 +4,7 @@
using
namespace
torchaudio
::
sox_utils
;
namespace
torchaudio
{
namespace
sox_effects_chain
{
namespace
torchaudio
::
sox_effects_chain
{
namespace
{
...
...
@@ -27,7 +26,8 @@ struct FileObjOutputPriv {
/// Callback function to feed byte string
/// https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/sox.h#L1268-L1278
int
fileobj_input_drain
(
sox_effect_t
*
effp
,
sox_sample_t
*
obuf
,
size_t
*
osamp
)
{
auto
fileobj_input_drain
(
sox_effect_t
*
effp
,
sox_sample_t
*
obuf
,
size_t
*
osamp
)
->
int
{
auto
priv
=
static_cast
<
FileObjInputPriv
*>
(
effp
->
priv
);
auto
sf
=
priv
->
sf
;
auto
buffer
=
priv
->
buffer
;
...
...
@@ -115,12 +115,12 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) {
return
(
priv
->
eof_reached
&&
!*
osamp
)
?
SOX_EOF
:
SOX_SUCCESS
;
}
int
fileobj_output_flow
(
auto
fileobj_output_flow
(
sox_effect_t
*
effp
,
sox_sample_t
const
*
ibuf
,
sox_sample_t
*
obuf
LSX_UNUSED
,
size_t
*
isamp
,
size_t
*
osamp
)
{
size_t
*
osamp
)
->
int
{
*
osamp
=
0
;
if
(
*
isamp
)
{
auto
priv
=
static_cast
<
FileObjOutputPriv
*>
(
effp
->
priv
);
...
...
@@ -128,7 +128,6 @@ int fileobj_output_flow(
auto
fp
=
static_cast
<
FILE
*>
(
sf
->
fp
);
auto
fileobj
=
priv
->
fileobj
;
auto
buffer
=
priv
->
buffer
;
auto
buffer_size
=
priv
->
buffer_size
;
// Encode chunk
auto
num_samples_written
=
sox_write
(
sf
,
ibuf
,
*
isamp
);
...
...
@@ -154,32 +153,32 @@ int fileobj_output_flow(
return
SOX_SUCCESS
;
}
sox_effect_handler_t
*
get_fileobj_input_handler
()
{
auto
get_fileobj_input_handler
()
->
sox_effect_handler_t
*
{
static
sox_effect_handler_t
handler
{
/*name=*/
"input_fileobj_object"
,
/*usage=*/
NULL
,
/*usage=*/
nullptr
,
/*flags=*/
SOX_EFF_MCHAN
,
/*getopts=*/
NULL
,
/*start=*/
NULL
,
/*flow=*/
NULL
,
/*getopts=*/
nullptr
,
/*start=*/
nullptr
,
/*flow=*/
nullptr
,
/*drain=*/
fileobj_input_drain
,
/*stop=*/
NULL
,
/*kill=*/
NULL
,
/*stop=*/
nullptr
,
/*kill=*/
nullptr
,
/*priv_size=*/
sizeof
(
FileObjInputPriv
)};
return
&
handler
;
}
sox_effect_handler_t
*
get_fileobj_output_handler
()
{
auto
get_fileobj_output_handler
()
->
sox_effect_handler_t
*
{
static
sox_effect_handler_t
handler
{
/*name=*/
"output_fileobj_object"
,
/*usage=*/
NULL
,
/*usage=*/
nullptr
,
/*flags=*/
SOX_EFF_MCHAN
,
/*getopts=*/
NULL
,
/*start=*/
NULL
,
/*getopts=*/
nullptr
,
/*start=*/
nullptr
,
/*flow=*/
fileobj_output_flow
,
/*drain=*/
NULL
,
/*stop=*/
NULL
,
/*kill=*/
NULL
,
/*drain=*/
nullptr
,
/*stop=*/
nullptr
,
/*kill=*/
nullptr
,
/*priv_size=*/
sizeof
(
FileObjOutputPriv
)};
return
&
handler
;
}
...
...
@@ -225,5 +224,4 @@ void SoxEffectsChainPyBind::addOutputFileObj(
}
}
}
// namespace sox_effects_chain
}
// namespace torchaudio
}
// namespace torchaudio::sox_effects_chain
torchaudio/csrc/pybind/sox/effects_chain.h
View file @
27e6779c
...
...
@@ -4,8 +4,7 @@
#include <torch/extension.h>
#include <torchaudio/csrc/sox/effects_chain.h>
namespace
torchaudio
{
namespace
sox_effects_chain
{
namespace
torchaudio
::
sox_effects_chain
{
class
SoxEffectsChainPyBind
:
public
SoxEffectsChain
{
using
SoxEffectsChain
::
SoxEffectsChain
;
...
...
@@ -24,7 +23,6 @@ class SoxEffectsChainPyBind : public SoxEffectsChain {
py
::
object
*
fileobj
);
};
}
// namespace sox_effects_chain
}
// namespace torchaudio
}
// namespace torchaudio::sox_effects_chain
#endif
torchaudio/csrc/pybind/sox/io.cpp
View file @
27e6779c
...
...
@@ -5,14 +5,14 @@
#include <torchaudio/csrc/sox/io.h>
#include <torchaudio/csrc/sox/types.h>
#include <utility>
using
namespace
torchaudio
::
sox_utils
;
namespace
torchaudio
{
namespace
sox_io
{
namespace
torchaudio
::
sox_io
{
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
get_info_fileobj
(
py
::
object
fileobj
,
c10
::
optional
<
std
::
string
>
format
)
{
auto
get_info_fileobj
(
py
::
object
fileobj
,
c10
::
optional
<
std
::
string
>
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
// Prepare in-memory file object
// When libsox opens a file, it also reads the header.
// When opening a file there are two functions that might touch FILE* (and the
...
...
@@ -71,16 +71,20 @@ std::tuple<int64_t, int64_t, int64_t, int64_t, std::string> get_info_fileobj(
get_encoding
(
sf
->
encoding
.
encoding
));
}
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
load_audio_fileobj
(
auto
load_audio_fileobj
(
py
::
object
fileobj
,
c10
::
optional
<
int64_t
>
frame_offset
,
c10
::
optional
<
int64_t
>
num_frames
,
c10
::
optional
<
bool
>
normalize
,
c10
::
optional
<
bool
>
channels_first
,
c10
::
optional
<
std
::
string
>
format
)
{
c10
::
optional
<
std
::
string
>
format
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
{
auto
effects
=
get_effects
(
frame_offset
,
num_frames
);
return
torchaudio
::
sox_effects
::
apply_effects_fileobj
(
fileobj
,
effects
,
normalize
,
channels_first
,
format
);
std
::
move
(
fileobj
),
effects
,
normalize
,
channels_first
,
std
::
move
(
format
));
}
namespace
{
...
...
@@ -94,8 +98,8 @@ struct AutoReleaseBuffer {
AutoReleaseBuffer
()
:
ptr
(
nullptr
),
size
(
0
)
{}
AutoReleaseBuffer
(
const
AutoReleaseBuffer
&
other
)
=
delete
;
AutoReleaseBuffer
(
AutoReleaseBuffer
&&
other
)
=
delete
;
A
uto
ReleaseBuffer
&
operator
=
(
const
AutoReleaseBuffer
&
other
)
=
delete
;
A
uto
ReleaseBuffer
&
operator
=
(
AutoReleaseBuffer
&&
other
)
=
delete
;
a
uto
operator
=
(
const
AutoReleaseBuffer
&
other
)
->
AutoReleaseBuffer
&
=
delete
;
a
uto
operator
=
(
AutoReleaseBuffer
&&
other
)
->
AutoReleaseBuffer
&
=
delete
;
~
AutoReleaseBuffer
()
{
if
(
ptr
)
{
free
(
ptr
);
...
...
@@ -148,7 +152,11 @@ void save_audio_fileobj(
const
auto
signal_info
=
get_signalinfo
(
&
tensor
,
sample_rate
,
filetype
,
channels_first
);
const
auto
encoding_info
=
get_encodinginfo_for_save
(
filetype
,
tensor
.
dtype
(),
compression
,
encoding
,
bits_per_sample
);
filetype
,
tensor
.
dtype
(),
compression
,
std
::
move
(
encoding
),
bits_per_sample
);
AutoReleaseBuffer
buffer
;
...
...
@@ -179,5 +187,4 @@ void save_audio_fileobj(
fileobj
.
attr
(
"write"
)(
py
::
bytes
(
buffer
.
ptr
,
buffer
.
size
));
}
}
// namespace sox_io
}
// namespace torchaudio
}
// namespace torchaudio::sox_io
torchaudio/csrc/pybind/sox/io.h
View file @
27e6779c
...
...
@@ -3,20 +3,18 @@
#include <torch/extension.h>
namespace
torchaudio
{
namespace
sox_io
{
namespace
torchaudio
::
sox_io
{
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
get_info_fileobj
(
py
::
object
fileobj
,
c10
::
optional
<
std
::
string
>
format
);
auto
get_info_fileobj
(
py
::
object
fileobj
,
c10
::
optional
<
std
::
string
>
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
load_audio_fileobj
(
auto
load_audio_fileobj
(
py
::
object
fileobj
,
c10
::
optional
<
int64_t
>
frame_offset
,
c10
::
optional
<
int64_t
>
num_frames
,
c10
::
optional
<
bool
>
normalize
,
c10
::
optional
<
bool
>
channels_first
,
c10
::
optional
<
std
::
string
>
format
);
c10
::
optional
<
std
::
string
>
format
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
;
void
save_audio_fileobj
(
py
::
object
fileobj
,
...
...
@@ -28,7 +26,6 @@ void save_audio_fileobj(
c10
::
optional
<
std
::
string
>
encoding
,
c10
::
optional
<
int64_t
>
bits_per_sample
);
}
// namespace sox_io
}
// namespace torchaudio
}
// namespace torchaudio::sox_io
#endif
torchaudio/csrc/pybind/sox/utils.cpp
View file @
27e6779c
#include <torchaudio/csrc/pybind/sox/utils.h>
namespace
torchaudio
{
namespace
sox_utils
{
namespace
torchaudio
::
sox_utils
{
uint64_t
read_fileobj
(
py
::
object
*
fileobj
,
const
uint64_t
size
,
char
*
buffer
)
{
auto
read_fileobj
(
py
::
object
*
fileobj
,
const
uint64_t
size
,
char
*
buffer
)
->
uint64_t
{
uint64_t
num_read
=
0
;
while
(
num_read
<
size
)
{
auto
request
=
size
-
num_read
;
...
...
@@ -28,5 +28,4 @@ uint64_t read_fileobj(py::object* fileobj, const uint64_t size, char* buffer) {
return
num_read
;
}
}
// namespace sox_utils
}
// namespace torchaudio
}
// namespace torchaudio::sox_utils
torchaudio/csrc/pybind/sox/utils.h
View file @
27e6779c
...
...
@@ -3,12 +3,10 @@
#include <torch/extension.h>
namespace
torchaudio
{
namespace
sox_utils
{
namespace
torchaudio
::
sox_utils
{
uint64_t
read_fileobj
(
py
::
object
*
fileobj
,
uint64_t
size
,
char
*
buffer
);
auto
read_fileobj
(
py
::
object
*
fileobj
,
uint64_t
size
,
char
*
buffer
)
->
uint64_t
;
}
// namespace sox_utils
}
// namespace torchaudio
}
// namespace torchaudio::sox_utils
#endif
torchaudio/csrc/sox/effects.cpp
View file @
27e6779c
...
...
@@ -5,8 +5,7 @@
using
namespace
torchaudio
::
sox_utils
;
namespace
torchaudio
{
namespace
sox_effects
{
namespace
torchaudio
::
sox_effects
{
namespace
{
...
...
@@ -25,6 +24,7 @@ void initialize_sox_effects() {
throw
std
::
runtime_error
(
"Failed to initialize sox effects."
);
};
SOX_RESOURCE_STATE
=
Initialized
;
break
;
case
Initialized
:
break
;
case
ShutDown
:
...
...
@@ -45,16 +45,17 @@ void shutdown_sox_effects() {
throw
std
::
runtime_error
(
"Failed to initialize sox effects."
);
};
SOX_RESOURCE_STATE
=
ShutDown
;
break
;
case
ShutDown
:
break
;
}
}
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
apply_effects_tensor
(
auto
apply_effects_tensor
(
torch
::
Tensor
waveform
,
int64_t
sample_rate
,
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
,
bool
channels_first
)
{
const
std
::
vector
<
std
::
vector
<
std
::
string
>>
&
effects
,
bool
channels_first
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
{
validate_input_tensor
(
waveform
);
// Create SoxEffectsChain
...
...
@@ -81,19 +82,20 @@ std::tuple<torch::Tensor, int64_t> apply_effects_tensor(
/*num_samples=*/
out_buffer
.
size
(),
/*num_channels=*/
chain
.
getOutputNumChannels
(),
dtype
,
/*nor
a
mlize=*/
false
,
/*norm
a
lize=*/
false
,
channels_first
);
return
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
(
out_tensor
,
chain
.
getOutputSampleRate
());
}
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
apply_effects_file
(
const
std
::
string
path
,
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
,
auto
apply_effects_file
(
const
std
::
string
&
path
,
const
std
::
vector
<
std
::
vector
<
std
::
string
>>
&
effects
,
c10
::
optional
<
bool
>
normalize
,
c10
::
optional
<
bool
>
channels_first
,
const
c10
::
optional
<
std
::
string
>&
format
)
{
const
c10
::
optional
<
std
::
string
>&
format
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
{
// Open input file
SoxFormat
sf
(
sox_open_read
(
path
.
c_str
(),
...
...
@@ -150,5 +152,4 @@ TORCH_LIBRARY_FRAGMENT(torchaudio, m) {
&
torchaudio
::
sox_effects
::
apply_effects_file
);
}
}
// namespace sox_effects
}
// namespace torchaudio
}
// namespace torchaudio::sox_effects
torchaudio/csrc/sox/effects.h
View file @
27e6779c
...
...
@@ -4,27 +4,26 @@
#include <torch/script.h>
#include <torchaudio/csrc/sox/utils.h>
namespace
torchaudio
{
namespace
sox_effects
{
namespace
torchaudio
::
sox_effects
{
void
initialize_sox_effects
();
void
shutdown_sox_effects
();
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
apply_effects_tensor
(
auto
apply_effects_tensor
(
torch
::
Tensor
waveform
,
int64_t
sample_rate
,
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
,
bool
channels_first
);
const
std
::
vector
<
std
::
vector
<
std
::
string
>>
&
effects
,
bool
channels_first
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
;
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
apply_effects_file
(
const
std
::
string
path
,
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
,
auto
apply_effects_file
(
const
std
::
string
&
path
,
const
std
::
vector
<
std
::
vector
<
std
::
string
>>
&
effects
,
c10
::
optional
<
bool
>
normalize
,
c10
::
optional
<
bool
>
channels_first
,
const
c10
::
optional
<
std
::
string
>&
format
);
const
c10
::
optional
<
std
::
string
>&
format
)
->
std
::
tuple
<
torch
::
Tensor
,
int64_t
>
;
}
// namespace sox_effects
}
// namespace torchaudio
}
// namespace torchaudio::sox_effects
#endif
torchaudio/csrc/sox/effects_chain.cpp
View file @
27e6779c
...
...
@@ -185,7 +185,7 @@ SoxEffect::operator sox_effect_t*() const {
return
se_
;
}
sox_effect_t
*
SoxEffect
::
operator
->
()
noexcept
{
auto
SoxEffect
::
operator
->
()
noexcept
->
sox_effect_t
*
{
return
se_
;
}
...
...
torchaudio/csrc/sox/effects_chain.h
View file @
27e6779c
...
...
@@ -14,11 +14,11 @@ struct SoxEffect {
explicit
SoxEffect
(
sox_effect_t
*
se
)
noexcept
;
SoxEffect
(
const
SoxEffect
&
other
)
=
delete
;
SoxEffect
(
const
SoxEffect
&&
other
)
=
delete
;
SoxEffect
&
operator
=
(
const
SoxEffect
&
other
)
=
delete
;
SoxEffect
&
operator
=
(
SoxEffect
&&
other
)
=
delete
;
auto
operator
=
(
const
SoxEffect
&
other
)
->
SoxEffect
&
=
delete
;
auto
operator
=
(
SoxEffect
&&
other
)
->
SoxEffect
&
=
delete
;
~
SoxEffect
();
operator
sox_effect_t
*
()
const
;
sox_effect_t
*
operator
->
()
noexcept
;
auto
operator
->
()
noexcept
->
sox_effect_t
*
;
private:
sox_effect_t
*
se_
;
...
...
torchaudio/csrc/sox/io.h
View file @
27e6779c
...
...
@@ -7,9 +7,10 @@
namespace
torchaudio
{
namespace
sox_io
{
std
::
vector
<
std
::
vector
<
std
::
string
>>
get_effects
(
auto
get_effects
(
const
c10
::
optional
<
int64_t
>&
frame_offset
,
const
c10
::
optional
<
int64_t
>&
num_frames
);
const
c10
::
optional
<
int64_t
>&
num_frames
)
->
std
::
vector
<
std
::
vector
<
std
::
string
>>
;
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
get_info_file
(
const
std
::
string
&
path
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment